你可以手动实现cocoa绑定?
我已经在我自己的NSView子类实现绑定了一个裂缝。 它可以工作,但从nib文件绑定到文件所有者时,保留周期存在问题。 稍微阅读一下后,我发现苹果几年前也有同样的问题,但是已经用一些无证的类(NSAutounbinder)修复了它。
关于保留周期问题,有一个冗长的讨论http://www.cocoabuilder.com/archive/message/cocoa/2004/6/12/109600 。 解决方法是在窗口控制器释放之前解除所有绑定,而不是在解除分配之前,放在像windowWillClose:这样的地方。 这对我来说似乎是一个不必要的手段。
我的问题是这样的:有没有办法使自定义绑定,以及由苹果公司的作品,而不使用无证的function? 我是否以错误的方式去做这件事?
更新2:我发现了一个解决scheme,允许手动实现的绑定工作完全像苹果的绑定。 它利用未logging的NSAutounbinder类,没有实际使用未logging的特征。 我将在今天晚些时候发布解决scheme。
更新: 我试着使用exposeBinding:
它似乎没有任何区别 。 然而, NSObject
的bind:toObject:withKeyPath:options:
一半的工作。 它传播从绑定到绑定(即从模型/控制器到查看)的变化,但不会以相反的方式工作。 而且,虽然绑定器显然被观察到, observeValueForKeyPath:ofObject:change:context:
从不被触发。
示例项目在这里: http : //www.tomdalling.com/wp-content/BindingsTest.zip
苹果的文档表明你实际上必须重写bind:toObject:withKeyPath:options:
来实现手动绑定。 看到这里: http : //developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/HowDoBindingsWork.html
侧注:我已经调查了无证的NSAutounbinder是如何工作的,这里是我所知道的。
绑定创build到NSWindowController时,绑定对象实际上是一个NSAutounbinder,从NSWindowController通过 – [NSWindowController _autounbinder]获取。 NSAutounbinder是NSWindowController对象的非保留代理。 避免保留周期问题是没有保留的。
当 – [NSWindowController release]被调用并且retainCount == 1时,NSAutounbinder将所有绑定解除绑定到它自己。 这确保在释放对象之前没有悬挂指针。
这是我能find的最佳解决scheme。 我在这里有一个更详细的讨论和演示代码: http : //tomdalling.com/blog/cocoa/implementing-your-own-cocoa-bindings/
基本上,你不要重写bind:toObject:withKeyPath:options:
或unbind:
bind:toObject:withKeyPath:options:
NSObject
的默认实现将使用NSAutounbinder
来避免保留周期。 正如Louis Gerbarg所指出的那样, NSAutounbinder
仍然存在的情况仍然存在。但是,您可以使绑定至less和Apple的绑定一样工作。
由于bind:toObject:withKeyPath:options:
的默认实现在视图更改时不更新模型,因此必须手动传播视图驱动的更改。 您可以使用-[NSObject infoForBinding:]
获取更新绑定对象所需的所有信息。 我在NSObject上添加了一个类别:
-(void)propagateValue:(id)value forBinding:(NSString*)binding;
它处理获取绑定对象,绑定关键path和应用值转换器。 实现可以从顶部的链接获得。
简短的回答是,不,你不能在调用代码和nib中没有解决方法。 即使NSAutounbinder错过了NSDocument和NSWindowController的一些情况下,如果苹果不能正确地为2个class级正常工作,他们专门build立我们这些没有访问内部AppKit的基本上没有机会。
话虽如此,有两种解决方法可能比在windowWillClose:中解除绑定好一点。
- 不要绑定到文件所有者,而是将一个NSObjectController作为根级对象拖放到nib中并绑定到它,然后在awakeFromNib期间在对象控制器上设置setContents:。
- 打开垃圾收集。 如果这是一个选项,它解决了所有的对象循环问题;-)显然,GC引入了自己的问题,如果你需要10.4兼容性,它是一个非起动器。
你可能想要签出NSKeyValueBindingCreation协议 。 它允许您通过代码以编程方式创build绑定。 (如果需要引用IBOutletvariables,请记住在awakeFromNib方法中执行此操作,否则它们可能为零)。
有关如何实现自己的绑定的一个很好的示例,请参阅mmalc的GraphicsBindings示例。 您需要实现NSKeyValueBindingCreation非正式协议才能使其工作。 为了让你的控制器知道可以绑定的东西,在视图的+(id)初始化方法中调用exposeBinding:
+ (void)initialize { [self exposeBinding:@"ILIKEBINDAGE"]; }
然后,您需要实现NSKeyValueBindingCreation协议中的每个绑定pipe理方法。 您基本上需要为视图设置KVO,以便知道何时根据应用程序的行为进行更新并处理清理(取消绑定:)。
这是很多额外的,相当丑陋的代码,所以它可能是使用传统胶水代码更好,更容易阅读。
- Xcode 6 iOS创build一个Cocoa Touch框架 – 体系结构问题
- 在IB之下IBOutlets应该强大还是弱?
- 如何使用Cocoa Auto Layout调整窗口的大小?
- 在更改transitionWithView内的rootViewController时泄漏视图
- 在Objective-C ++ Cocoa中将RGB数据转换成位图
- 相当于-respondsToSelector的类方法:
- 对UITableViewCell的accessoryView使用自定义图像,并使其响应UITableViewDelegate
- 使NSRunLoop等待标志被设置的最佳方法?
- iPhone UITableView单元保持选定状态