协调一对NSTextField控件

时间:2013-12-02 15:04:02

标签: cocoa nstextfield nscontrol

我有一个带有两个NSTextField控件的窗口,其值必须保持彼此同步。具体地,一个是宽度而另一个是长度,它们的比率应保持等于给定的纵横比。我希望用户能够设置他们喜欢的任何一个,并自动进行另一个更新。

我的第一种方法:我将两个控件中的每个控件的委托设置为窗口控制器。我实现了controlTextDidEndEditing方法。我检查发件人。如果是宽度字段,我计算高度字段并通过bound属性更新其值(self.my_height = self.my_width / aspectRatio)。同样,如果它是高度字段,(self.my_width = self.my_height * aspectRatio)。

但是我遇到了障碍。假设纵横比为1.5。用户在宽度字段中输入100,然后移动到另一个字段。高度字段更新为66(无论好坏,我选择总是向下舍入)。用户单击高度字段,不进行任何更改,并在其他位置单击。宽度字段更新为99.用户正在刮他/她的头。

我的提炼。我还在窗口控制器中实现了controlTextDidChange方法。所有这一切都将静态(文件作用域)BOOL变量(gTextFieldDidChange)设置为YES。现在,当我输入controlTextDidEndEditing时,我检查gTextFieldDidChange的状态。如果不是,那我立刻回来。如果是,那么我将gTextFieldDidChange清除回NO并处理长度/宽度更新。

这似乎对我没有任何问题,但似乎相当“后门”。 我缺少一种更清洁/更聪明的方法吗?

感谢任何/所有建议。 麦克

2 个答案:

答案 0 :(得分:1)

以下代码使用NSTextFieldDelegate>方法执行您想要的操作:

@interface HASMainViewController () <NSTextFieldDelegate>
@property (weak) IBOutlet NSTextField *widthTextField;
@property (weak) IBOutlet NSTextField *heightTextField;
@property (weak) IBOutlet NSTextField *ratioLabel;
@end

@implementation HASMainViewController

- (void)awakeFromNib {
    self.widthTextField.delegate = self;
    self.heightTextField.delegate = self;
    self.ratioLabel.stringValue = @"1.777777"; // 16:9 (1920 x 1080)
}

- (void)controlTextDidChange:(NSNotification *)obj {
    if (obj.object == self.widthTextField) {
        // If the width textfield gets changed we want to pass its value and -1 for calculating the height.
        // After that we set the height's text field to the calculated value.
        self.heightTextField.integerValue = [self calculateRatioComponentWithWidth:self.widthTextField.integerValue height:-1 ratio:self.ratioLabel.doubleValue];
    } else if (obj.object == self.heightTextField) {
        // If the width textfield gets changed we want to pass its value and -1 for calculating the height.
        // After that we set the height's text field to the calculated value.
        self.widthTextField.integerValue = [self calculateRatioComponentWithWidth:-1 height:self.heightTextField.integerValue ratio:self.ratioLabel.doubleValue];
    }
}

/**
 *  This method calculates the missing component (determined by "-1") for a given ratio.
 *
 *  @param width  An NSInteger representing the width. Pass -1 if this value should be calculated.
 *  @param height An NSInteger representing the height. Pass -1 if this value should be calculated.
 *  @param ratio  The ratio which needs to be kept.
 *
 *  @return An NSInteger which is depending on the what you passed as parameters the calculated width or height.
 *
 *  @discussion This method raises an HASInternalInconsistencyException exception if both width and height parameters are -1.
 *
 */
- (NSInteger)calculateRatioComponentWithWidth:(NSInteger)width height:(NSInteger)height ratio:(double)ratio {
    if (width == -1 && height == -1) [[NSException exceptionWithName:@"HASInternalInconsistencyException"
                                                              reason:@"Both width and height are -1 (to be calculated)."
                                                            userInfo:nil] raise];
    // Calculate new width
    if (width == -1) return (NSInteger)round(height * ratio);
    // Calculate new width
    else if (height == -1) return (NSInteger)round(width * 1 / ratio);
    // Just to silence the compiler
    return 0;
}

@end

您可以从我刚刚为您制作的Bitbucket Repository克隆或下载一个小样本应用; - )

答案 1 :(得分:0)

我实际上找到了比我最初尝试的更好更简单的解决方案,以及HAS的建议。

我只是检查了值绑定下的“持续更新值”框。 这样做意味着在调用controlTextDidChange之前更新绑定值。

我现在可以在键入时进行更正,不再需要延迟调用controlTextDidEndEditting。