Manual binding in Cocoa

流过昼夜 提交于 2019-12-04 16:06:47

As @nick says, you want Key-Value-Observing.

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

Then when isLocked changes the -observeValueForKeyPath:ofObject:change:context: method that you have added to your viewController will be called (as long as you only manipulate isLocked in a KVC compliant way).

The options parameter lets you optionally tweak exactly what conditions will trigger the notification and what data is sent along with the notification. The context parameter is there to help you distinguish between notifications that you registered to receive and notifications your superclass registered to receive. It is optional.

Bindings seem like they might be useful to keep two values in sync. However, this is not what they do at all.

Yes, lots of things seem to give the impression that this is what they do, and there isn't much saying that this isn't what they do, also lots of people believe that this is what they do - but no, you cannot use them for this.

Only a handful of classes support bindings (they are listed here) and then, and this is the important bit, those classes only support binding their named bindings, and these bindings are not instance variables. eg NSTextField has a 'fontFamilyName' binding yet NSTextField does not have a 'fontFamilyName' property or instance variable, even a derived one. NSTextField does have a 'isBordered' property but not a binding - so you cannot bind 'isBordered'.

It does not mean anything to 'bind' an arbitrary property of an arbitrary Class.

Yes, you can bind two arbitrary values, the following code works just fine:

#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;
}

As far as I can tell, the problem is the bit [ArrayController selection]. The first problem is that ArrayController is (or should be) a class, and getting the class's selection is probably pointless. The other problem is that even if this were an instance, you would be binding to the selection at the time of the call, which is almost certainly not what you want. You want to track the current selection as it changes.

So what you want is probably something like the following:

[myViewController bind:@"value" toObject:myArrayController withKeyPath:@"selection.isLocked" options:nil];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!