你能手动实现 Cocoa 绑定吗? [英] Can you manually implement Cocoa bindings?

查看:17
本文介绍了你能手动实现 Cocoa 绑定吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在为我自己的 NSView 子类实现绑定方面遇到了困难.它可以工作,但是当从 nib 文件绑定到 File's Owner 时,存在保留周期问题.仔细阅读后,我发现几年前 Apple 也有同样的问题,但已经用一些神奇的无证类 (NSAutounbinder) 修复了它.

I've had a crack at implementing bindings for my own NSView subclass. It works, but there are problems with retain cycles when binding to File's Owner from a nib file. After reading into it a little, I discovered that Apple had the same problem a few years back but have fixed it with some magic undocumented class (NSAutounbinder).

这里有一个关于保留循环问题的冗长讨论 http://www.cocoabuilder.com/archive/message/cocoa/2004/6/12/109600 .解决方法是在窗口控制器释放之前解除所有绑定,而不是在它解除分配之前,在像 windowWillClose: 这样的地方.这对我来说似乎是不必要的黑客攻击.

There is a lengthy discussion of the retain cycle problem here http://www.cocoabuilder.com/archive/message/cocoa/2004/6/12/109600 . The workaround is to to unbind all bindings before the window controller is released, not before it is deallocated, in a place like windowWillClose:. This seems like an unnecessary hack to me.

我的问题是:有没有什么方法可以在不使用未记录的功能的情况下制作与 Apple 制作的绑定一样有效的自定义绑定?我是不是用错了方法?

My question is this: Is there any way to make custom bindings that work as well as the ones made by Apple, without using undocumented features? Am I going about this the wrong way?

更新 2:我找到了一个解决方案,它允许手动实现的绑定与 Apple 的绑定完全一样工作.它利用了未记录的 NSAutounbinder 类,而不实际使用未记录的功能.我将在今天晚些时候发布解决方案.

UPDATE 2: I have found a solution that allows manually implemented bindings to work exactly like Apple's bindings. It takes advantage of the undocumented NSAutounbinder class, without actually using undocumented features. I will post the solution later today.

更新:我已经尝试过使用 exposeBinding:,但它似乎没有任何区别.但是,bind:toObject:withKeyPath:options:NSObject 实现一半有效.它传播从绑定者到绑定者的更改(即从模型/控制器到视图),但不会以相反的方式工作.此外,虽然显然绑定者正在被观察到,observeValueForKeyPath:ofObject:change:context: 永远不会被触发.

UPDATE: I've tried using exposeBinding:, and it doesn't seem to make any difference. However, the NSObject implementation of bind:toObject:withKeyPath:options: half works. It propogates changes from bindee to binder (i.e. from model/controller to view), but doesn't work the opposite way. Also, although the bindee is obviously being observed, observeValueForKeyPath:ofObject:change:context: is never triggered.

此处的示例项目:http://www.tomdalling.com/wp-content/绑定测试.zip

Apple 的文档表明,实际上,您必须重写 bind:toObject:withKeyPath:options: 以实现手动绑定.请参阅此处:http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/HowDoBindingsWork.html

Apple's documentation indicates that you do, in fact, have to override bind:toObject:withKeyPath:options: to implement manual bindings. See here: http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/HowDoBindingsWork.html

旁注:我调查了未记录的 NSAutounbinder 是如何工作的,这就是我所知道的.

SIDE NOTE: I've investigated how the undocumented NSAutounbinder works, and here's what I know.

当一个绑定被创建到一个 NSWindowController 时,绑定的对象实际上是一个 NSAutounbinder,它是从 NSWindowController 中通过 -[NSWindowController _autounbinder] 获取的.NSAutounbinder 是 NSWindowController 对象的非保留代理.非保留是为了避免保留循环问题.

When a binding is created to an NSWindowController, the bound object is actually an NSAutounbinder that is acquired from the NSWindowController with -[NSWindowController _autounbinder]. NSAutounbinder is a non-retaining proxy for the NSWindowController object. It is non-retaining to avoid the retain cycle problem.

当 -[NSWindowController release] 被调用并且 retainCount == 1 时,NSAutounbinder 将所有绑定解除绑定到自身.这可确保在释放对象之前没有指向该对象的悬空指针.

When -[NSWindowController release] is called and retainCount == 1, The NSAutounbinder unbinds all bindings to itself. This ensures that there are no dangling pointers to the object before it is deallocated.

推荐答案

这是我能找到的最佳解决方案.我在这里有更详细的讨论和演示代码:http://tomdalling.com/blog/cocoa/implementing-your-own-cocoa-bindings/

Here is the best solution I can find. I've got a more detailed discussion and demo code here: http://tomdalling.com/blog/cocoa/implementing-your-own-cocoa-bindings/

基本上,您不要覆盖bind:toObject:withKeyPath:options:unbind:.NSObject 上的默认实现将使用 NSAutounbinder 来避免保留循环.正如 Louis Gerbarg 指出的那样,仍然存在 NSAutounbinder 无法启动的情况.但是,您至少可以让绑定与 Apple 的绑定一样正常工作.

Basically, you DO NOT override bind:toObject:withKeyPath:options: or unbind:. The default implementation on NSObject will use NSAutounbinder to avoid retain cycles. As Louis Gerbarg pointed out, there are still situations where NSAutounbinder doesn't kick in. However, you can get your bindings working at least as well as Apple's bindings.

由于 bind:toObject:withKeyPath:options: 的默认实现不会在视图更改时更新模型,因此必须手动传播视图驱动的更改.您可以使用 -[NSObject infoForBinding:] 来获取更新绑定对象所需的所有信息.我在 NSObject 上添加了自己的方法,并带有一个类别:

Because the default implementation of bind:toObject:withKeyPath:options: doesn't update the model when the view changes, view-driven changes must be propagated manually. You can use -[NSObject infoForBinding:] to get all the information necessary to update the bound object. I've added my own method on NSObject with a category:

-(void)propagateValue:(id)value forBinding:(NSString*)binding;

它处理获取绑定对象、绑定键路径和应用值转换器.可从顶部的链接获得实现.

It handles getting the bound object, the bound key path, and applying the value transformer. The implementation is available from the link at the top.

这篇关于你能手动实现 Cocoa 绑定吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆