Manual binding in Cocoa

巧了我就是萌 提交于 2019-12-21 21:39:34

问题


I have an ImageView which shows a lock, informing if an opened file is locked or not. I have 2 images for locked and unlocked cases. I want synchronize the displayed image with boolean value of my object representing an opened file.

To do this I want my ViewController to change the image in my ImageView depending on lock state of object. So both object and ViewController have a property "isLocked".

How can I synchronize them? It is easy in IB but I don't know how to do it programmatically. I tried in initialize method of my ViewController to use:

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

But it doesn't work. In documentation it is said that I have to expose my binding before using it.

I try to put the following code in initializer method of my object:

[self exposeBinding:@"isLocked"];

But Xcode doesn't recognize this method.

Does somebody have experience with this kind of bindings establishing?


回答1:


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.




回答2:


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];


来源:https://stackoverflow.com/questions/5528608/manual-binding-in-cocoa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!