我无法理解Cocoa绑定.有人可以用人类可感知的方式向我解释这是什么吗?
绑定是一个系统,用于将视图连接到控制器,而无需编写大量的粘合代码,以使它们明确地相互通信.您所要做的就是在两个类中设置属性*并在IB中连接绑定.
传统方法是视图具有一个或多个与控制器通信的插座(最通用的示例是delegate
和target
),并且控制器具有与视图对话的插座.当控制器更新模型时,它会发送(例如)[view modelChange:newModelObject]
.当视图想要更新模型时,它会向其委托(控制器)发送一些委托消息,例如NSText textDidChange:
.
使用Bindings,您在代码中所要做的就是在视图上实现属性并在控制器上使用属性,然后将视图的一个或多个属性公开为绑定*.然后你只需要挂钩绑定.如果它是一个Cocoa类,那就是蛋糕:只需在IB中设置它.如果它是您自己的自定义类,您可能会bind:toObject:withKeyPath:options:
自己编写消息(并不是更难).
让我重申一下:使用Bindings,您的整个胶水代码(大部分时间)都[view bind:@"viewProperty" toObject:self withKeyPath:@"controllerProperty.modelProperty" options:options];
在控制器中.其他所有内容都由幕后的Bindings和KVO系统以及您的属性访问者处理.
缺点是您必须严格遵守Cocoa Bindings的要求.这些很简单,但许多旧的应用程序的设计方式不适合Cocoa Bindings.
您必须创建真实的模型对象,而不仅仅是传递原始对象(例如,字典数组).如果您正在使用Core Data,这很容易:您的托管对象是模型对象.
您必须正确编写访问者或合成正确的访问者.例如,NSString属性应该始终是@property(copy)
,永远不会@property(retain)
(因为否则,你会发现自己保留了别人的可变字符串,然后当你持有它时它们会变异).
您只能通过其属性(model.foo = bar
)或访问者消息([model setFoo:bar]
)更改模型对象的属性,而不能通过直接实例变量访问来更改.(访问器方法本身的明显例外,如果你自己编写,因为它们必须直接访问实例变量.)
有两个好处:
您可以编写一个全新的视图类,而无需删除大量的胶水代码.您必须删除的最多是bind::::
旧视图属性的一些消息.如果,在未来的几年内,您决定当前的视图无法扩展到您的应用程序的即将到来的功能,这使您可以灵活地将其撕掉并以最小的痛苦重新开始.
更重要的是,您需要阅读的代码越少,就越容易阅读它.
*并且,根据文档,在视图类中实现KVO观察方法,但我从来没有真正必须这样做.我提交了文档错误.
添加2009-03-07:啊,发现了引文."NSView子类可以通过为每个属性调用类方法exposeBinding:来将其他键值编码/键值观察兼容属性公开为绑定." - NSKeyValueBindingCreation因此您不需要实现KVO观察方法.
以前的答案是非常全面和良好的,我只是想我会添加一个答案解释它的核心是什么而不涉及Cocoa或Objective-C.这是因为这个概念本身就是语言无关,虽然像Objective-C的动态语言使得它成为很多不是像C++更静态的语言更容易.
假设你有两个对象中号和V.M有方法:
setX(int x); setY(int y); int getX(); int getY();
虽然V有方法:
setA(int x); setB(int y); int getA(); int getB();
一种看待这种情况的方法是M具有属性x和y,而V具有属性a和b.你想特性变化的X引起特性的变化,b和改变Ÿ引起的变化一个.
通过改变属性x,我们的意思是:
M.setX(10)
之前的地方
M.getX() != 10
因此,我们要的呼叫setX的上中号造成的通话组A上V.
允许您说什么绑定是对象V上的属性b绑定到对象M上的属性x.然后自动处理此更新.作为编码人员,您不必编写检查x是否已更改的代码,然后在V上调用setB.绑定自动处理这个问题.
绑定允许您将两个属性绑定在一起,这两个属性存在于两个不同的对象上,因此更改其中一个属性的值会导致另一个对象中的依赖属性更改为相同的值.