Cocoa中的手动绑定

时间:2011-04-03 08:57:49

标签: cocoa binding bind manual

我有一个显示锁定的ImageView,通知是否已锁定打开的文件。锁定和解锁的情况我有2张图片。我希望将显示的图像与表示打开文件的对象的布尔值同步。

为此,我希望我的ViewController根据对象的锁定状态更改ImageView中的图像。因此object和ViewController都有一个属性“isLocked”。

如何同步它们?在IB中很容易,但我不知道如何以编程方式进行。我尝试使用我的ViewController的初始化方法:

[ViewController bind:@"value" toObject:[ArrayController selection] withKeyPath:@"isLocked" options:nil];

但它不起作用。在文档中,据说我必须在使用它之前公开我的绑定。

我尝试将以下代码放在我的对象的初始化方法中:

[self exposeBinding:@"isLocked"];

但Xcode无法识别此方法。

有人有建立这种绑定的经验吗?

2 个答案:

答案 0 :(得分:6)

正如@nick所说,你想要Key-Value-Observing。

[arrayController addObserver:self 
                forKeyPath:@"selection.isLocked"
                options:NSKeyValueObservingOptionNew
                context:@"this_context"]

然后当isLocked更改-observeValueForKeyPath:ofObject时:更改:context:将调用已添加到viewController的方法(只要您只以符合KVC的方式操作isLocked)。

options参数允许您选择性地调整将触发通知的条件以及与通知一起发送的数据。 context参数用于帮助您区分注册接收的通知和超级注册接收的通知。这是可选的。

绑定似乎可能有助于保持两个值同步。但是,这不是他们所做的

是的,许多事情似乎给人的印象是这就是他们的所作所为,并没有多少人说这不是他们所做的,也有很多人认为这就是他们所做的 - 但没有,你不能使用它们。

只有少数几个类支持绑定(they are listed here)然后,这是重要的一点,这些类仅支持绑定其命名的绑定,以及这些绑定不是实例变量。例如, NSTextField 具有' fontFamilyName '绑定,但NSTextField 没有'fontFamilyName'属性或实例变量,甚至是派生的.NSTextField确实有'isBordered'属性但不是绑定 - 所以你不能绑定'isBordered'。

它并不意味着“绑定”任意类的任意属性。

答案 1 :(得分:1)

是的,您可以绑定两个任意值,以下代码可以正常工作:

#import <Cocoa/Cocoa.h>

@interface SomeObject : NSObject

@property (retain,nonatomic) id someValue;

@end
@implementation SomeObject

@end

int main()
{
   SomeObject *source=[SomeObject new];
   SomeObject *target=[SomeObject new];

   [target bind:@"someValue" toObject:source withKeyPath:@"someValue" options:0];
   [source bind:@"someValue" toObject:target withKeyPath:@"someValue" options:0];

   [source setSomeValue:@(42)];
   NSLog(@"target: %@",[target someValue]);


   [target setSomeValue:@(22)];
   NSLog(@"source: %@",[source someValue]);

  return 0;
}

据我所知,问题是位[ArrayController selection]。第一个问题是ArrayController是(或应该是)一个类,获得类的选择可能毫无意义。另一个问题是即使这是一个实例,你也会在调用时绑定选择,这几乎肯定不是你想要的。您希望在更改时跟踪当前选择。

所以你想要的可能是以下内容:

[myViewController bind:@"value" toObject:myArrayController withKeyPath:@"selection.isLocked" options:nil];