bind:toObject:withKeyPath:options:是单向绑定吗?

时间:2013-02-08 14:59:54

标签: cocoa binding cocoa-bindings nstextview

我有两个窗口:窗口A是从NIB加载的;和Window B以编程方式创建。

两个窗口都有一个NStextView:窗口A中textview的attributionString绑定到模型的属性text使用IB ;而使用text方法将Window B中textview的attributesString绑定到模型的-[NSObject bind:toObject:withKeyPath:options:]属性。

[textview bind:@"attributedString"
      toObject:obj
   withKeyPath:@"text"
       options:nil];

这是奇怪的事情:Window B中的textview确实绑定到obj.text,但textview中的更改永远不会更新为obj.text。但是,如果我在窗口A的文本视图中进行了更改,则obj.text和窗口B中的textview会相应更新。

所以我在想,-[NSObject bind:toObject:withKeyPath:options:]方法仅适用于单向绑定。我在Cocoa文件中找不到明确的解释。有没有人遇到过这个问题?如何在代码中实现双向绑定?

2 个答案:

答案 0 :(得分:4)

Cocoa绑定本质上是双向的,但某些行为(如文本字段的连续/实时更新)需要设置特定选项。在IB中,您需要确保选中“连续更新值”复选框。要以编程方式获得等效行为,您需要在绑定上指定options。这可能看起来像这样:

[textview bind: NSAttributedStringBinding 
      toObject: obj 
   withKeyPath: @"text" 
       options: (@{ 
                 NSContinuouslyUpdatesValueBindingOption : @YES })];

值得一提的是,在以编程方式设置绑定时,值得检查IB中的等效绑定并确保将所有相同的设置传递给程序绑定。例如,我在IB中看到,默认情况下,对于NSTextView的Attributed String绑定,都会选中“允许编辑多个值选择”,“有条件地设置可编辑”和“引发不适用键”选项。这意味着我们的程序化绑定应该真的看起来像:

[textview bind: NSAttributedStringBinding 
      toObject: obj 
   withKeyPath: @"text" 
       options: (@{ 
                 NSContinuouslyUpdatesValueBindingOption : @YES,
                 NSAllowsEditingMultipleValuesSelectionBindingOption : @YES,
                 NSConditionallySetsEditableBindingOption : @YES,
                 NSRaisesForNotApplicableKeysBindingOption : @YES })];

答案 1 :(得分:1)

是的, bind:toObject:withKeyPath:options:是一种方式,没有任何选项可以影响这一点。这与您在.nib文件中进行绑定不同。像往常一样,苹果忘记在其文档中提到这么简单的事情。这里最简单的解决方案是在创建前向绑定的同时创建反向绑定。 分配值时,这不会使代码死循环。 以下是用户默认值的示例:

// two way binding of MyObject.myValue to user defaults
[NSUserDefaultsController.sharedUserDefaultsController.values bind: @"myValueInDefaults"
                                                          toObject: myObject
                                                       withKeyPath: @"myValue"
                                                           options: @{@"NSContinuouslyUpdatesValue":@YES}];

[myObject bind: @"myValue"
      toObject: NSUserDefaultsController.sharedUserDefaultsController
   withKeyPath: @"values.myValueInDefaults"
       options: @{@"NSContinuouslyUpdatesValue":@YES}];