【发布时间】:2008-12-14 20:21:28
【问题描述】:
我有一个 NSView 子类,它具有我想要绑定的属性。我在子类中实现了以下内容:
myView.h:
@property (readwrite, retain) NSArray *representedObjects;
myView.m:
@synthesize representedObjects;
+(void)initialize
{
[self exposeBinding: @"representedObjects"];
}
-(void)bind:(NSString *)binding toObject:(id)observableController withKeyPath:(NSString *)keyPath options:(NSDictionary *)options
{
if ([binding isEqualToString:@"representedObjects"]) {
[observableController addObserver: self forKeyPath:@"arrangedObjects" options:NSKeyValueChangeNewKey context:nil];
} else {
[super bind: binding toObject:observableController withKeyPath:keyPath options: options];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"arrangedObjects"]) {
[self setRepresentedObjects: [object arrangedObjects]];
}
}
然后我在-[AppController awakeFromNib] 中创建与arrayController 的绑定:
[myView bind:@"representedObjects" toObject:arrayController withKeyPath:@"arrangedObjects" options: nil];
这是实现绑定的正确方法吗?它涉及很多样板代码,让我觉得我做错了什么。
我认为 NSObject 会自动实现我在-bind:toObject:withKeyPath:options: 中手动完成的操作,但事实并非如此。如果我注释掉我的-bind:toObject:withKeyPath:options:,则永远不会调用 setRepresentedObjects 方法。
附加信息:
我做了更多的调查,得出的结论是我原来的方法是正确的,你必须超越-bind:toObject:withKeyPath:options:。这是Cocoa Bindings Programming Topics: How Do Bindings Work?的引述:
在其 bind:toObject:withKeyPath:options: 方法中,对象必须至少执行以下操作:
- 确定要设置的绑定
- 使用什么键路径和什么选项记录它绑定到的对象
- 注册为绑定对象的 keypath 的观察者,以便接收更改通知
清单 2 中的代码示例显示了操纵杆的 bind:toObject:withKeyPath:options: 方法的部分实现,该方法仅处理角度绑定。
清单 2 Joystick 类的 bind:toObject:withKeyPath:options 方法的部分实现:
static void *AngleBindingContext = (void *)@"JoystickAngle"; - (void)bind:(NSString *)binding toObject:(id)observableObject withKeyPath:(NSString *)keyPath options:(NSDictionary *)options { // Observe the observableObject for changes -- note, pass binding identifier // as the context, so you get that back in observeValueForKeyPath:... // This way you can easily determine what needs to be updated. if ([binding isEqualToString:@"angle"]) { [observableObject addObserver:self forKeyPath:keyPath options:0 context:AngleBindingContext]; // Register what object and what keypath are // associated with this binding observedObjectForAngle = [observableObject retain]; observedKeyPathForAngle = [keyPath copy]; // Record the value transformer, if there is one angleValueTransformer = nil; NSString *vtName = [options objectForKey:@"NSValueTransformerName"]; if (vtName != nil) { angleValueTransformer = [NSValueTransformer valueTransformerForName:vtName]; } } // Implementation continues...
这清楚地表明 Joystick 类(它是一个 NSView 子类)需要覆盖 -bind:toObject:withKeyPath:options:。
我觉得这很令人惊讶。我对这个结论持怀疑态度,因为我没有发现其他代码示例可以做到这一点。但是,正如 Apple 官方文档所说,我应该超越 -bind:toObject:withKeyPath:options:,我认为这是正确的方法。
如果有人能证明我错了,我会非常高兴!
【问题讨论】:
-
更多活动的相关问题,关于双向更新的绑定:stackoverflow.com/questions/1169097/…
标签: objective-c cocoa cocoa-bindings