Need some tips regarding the Cocoa MVC/KVO patterns
这是一个非常广泛/模糊的问题,但这里是。提前道歉。
我正在构建的应用程序(桌面应用程序)采用不同类型的输入来生成 QR 码(我正在构建它来学习一些 Obj-C/Cocoa)。用户可以在允许输入纯文本(单个文本字段)、VCard/MeCard 数据(多个文本字段)和其他内容的不同视图之间切换。无论输入什么,结果都是二维码。
为了控制内容,我希望将视图用作视图控制器,以便它们处理自己的输入,并且可以简单地"发送"一个通用的"数据编码"对象包含所有数据到中央编码器。 IE。纯文本视图将使用其文本字段的文本生成数据对象,而 VCard/MeCard 视图将使用其所有字段来生成结构化 VCard/MeCard 数据。
我可以在代码中手动将所有这些东西绑定在一起,但我真的很想了解绑定/KVO 可以如何帮助我。唉,在阅读了 Apple 的开发人员文档以及我能找到的更简单的教程/示例之后,我仍然不确定如何将它应用到我的应用程序中。
例如:用户在 VCard 视图中编辑文本字段。每次更新都会通知 VCard 视图控制器并"重新计算"数据对象。然后通知中央编码器控制器更新的数据对象,并对数据进行编码。
这一切的重点是输入视图可以完全独立创建,并且可以包含各种输入字段。然后他们处理自己的输入,并"返回"一个通用数据对象,编码器可以使用该对象。在内部,视图观察它们的输入以更新数据对象,而在外部,编码器只需要观察数据对象。
问题是我不知道如何让这一切发生并保持解耦。输入视图和它的字段之间应该有一个对象控制器吗?视图和编码器之间应该有另一个吗?我在哪里需要什么?如果有人有一个好的教程的链接,请分享。
同样,我可以推出自己的通知系统和粘合代码,但我认为关键是要避免这种情况。
绝对是一个模糊的问题,但一个初学者对另一个,我感到你的痛苦:)
我下载并解压了每个示例,并经常使用 grep 搜索它们。我发现这是让我度过难关的最有价值的事情。我绝对建议不要放弃这些例子。我破解了这个脚本来下载并解压它们。
就良好的 KVO 模式而言,我发现这里描述的技术非常有用。但是,它在 Objective-C 2.0 中不能按原样工作。他也没有详细说明它的实际使用方式。这是我的工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #import <Foundation/Foundation.h> @interface KVODispatcher : NSObject { id owner; } @property (nonatomic, retain) id owner; - (id) initWithOwner:(id)owner; - (void)startObserving:(id)object keyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options selector:(SEL)sel; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #import"KVODispatcher.h" #import <objc/runtime.h> @implementation KVODispatcher @synthesize owner; - (id)initWithOwner:(id)theOwner { self = [super init]; if (self != nil) { self.owner = theOwner; } return self; } - (void)startObserving:(id)object keyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options selector:(SEL)sel { // here is the actual KVO registration [object addObserver:self forKeyPath:keyPath options:options context:sel]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // The event is delegated back to the owner // It is assumed the method identified by the selector takes // three parameters 'keyPath:object:change:' objc_msgSend(owner, (SEL)context, keyPath, object, change); // As noted, a variation of this technique could be // to expand the data passed in to 'initWithOwner' and // have that data passed to the selected method here. } @end |
然后你可以像这样注册观察事件:
1 2 3 4 5 | KVODispatcher* dispatcher = [[KVODispatcher alloc] initWithOwner:self]; [dispatcher startObserving:theObject keyPath:@"thePath" options:NSKeyValueChangeNewKey selector:@selector(doSomething:object:change:)]; |
在执行上述操作的同一个对象中,你可以有这样的方法:
1 2 3 4 5 6 | - (void) doSomething:(NSString *)keyPath object:(id)object change:(NSDictionary *)change { // do your thing } |
您可以拥有任意数量的"doSomething"类型方法。只要他们使用相同的参数 (keyPath:object:change:) 就可以了。每个对象有一个调度程序,希望接收有关任意数量对象更改的任意数量通知。
我喜欢它的地方:
一个不错的变化可能是将另一个字段(如