gpt4 book ai didi

cocoa - 需要一些有关 Cocoa MVC/KVO 模式的提示

转载 作者:行者123 更新时间:2023-12-03 16:15:08 25 4
gpt4 key购买 nike

这是一个非常广泛/模糊的问题,但这里是。提前致歉。

我正在构建的应用程序(桌面应用程序)需要不同类型的输入来生成 QR 码(我只是构建它来学习一些 Obj-C/Cocoa)。用户可以在允许输入纯文本(单个文本字段)、VCard/MeCard 数据(多个文本字段)和其他内容的不同 View 之间切换。无论输入什么,结果都是二维码。

为了保持内容包含,我想使用 View 作为 View Controller ,这样它们就可以处理自己的输入,并且可以简单地“发送”一个包含所有数据的通用“要编码的数据”对象中央编码器。 IE。纯 TextView 将使用其文本字段的文本创建一个数据对象,而 VCard/MeCard View 将使用其所有字段来创建结构化 VCard/MeCard 数据。

我可以在代码中手动将所有这些东西绑定(bind)在一起,但我真的很想了解绑定(bind)/KVO 如何帮助我。唉,在阅读了 Apple 的开发人员文档以及我能找到的更简单的教程/示例之后,我仍然不确定如何将其应用到我的应用程序中。

例如:用户在 VCard View 中编辑文本字段。 VCard View Controller 会收到每次更新的通知,并“重新计算”数据对象。然后,中央编码器 Controller 收到更新的数据对象的通知,并对数据进行编码。

所有这一切的要点是输入 View 可以完全独立地创建,并且可以包含各种输入字段。然后,它们处理自己的输入,并“返回”编码器可以使用的通用数据对象。在内部, View 观察它们的输入来更新数据对象,而在外部,编码器只需要观察数据对象。

问题是我不知道如何让这一切发生并保持分离。输入 View 及其字段之间是否应该有一个对象 Controller ? View 和编码器之间是否应该有另一个?我需要什么,在哪里?如果有人有优秀教程的链接,请分享。

同样,我可以推出自己的通知系统和粘合代码,但我认为重点是避免这种情况。

最佳答案

绝对是一个模糊的问题,但是一个初学者对另一个初学者来说,我感受到你的痛苦:)

我下载并解压了每个示例,并经常对它们进行 grep。我发现这是帮助我渡过难关的最有值(value)的事情。我绝对建议不要放弃这些例子。我破解了 this script 来下载并解压它们。

就良好的 KVO 模式而言,我发现 described here 技术非常有用。然而,在 Objective-C 2.0 中它是 doesn't work as-is 。他也没有详细说明它的实际使用方式。这是我所做的工作:

KVODispatcher.h如下所示:

#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

KVODispatcher.m 如下:

#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

然后你可以注册观察事件,如下所示:

KVODispatcher* dispatcher = [[KVODispatcher alloc] initWithOwner:self];
[dispatcher startObserving:theObject
keyPath:@"thePath"
options:NSKeyValueChangeNewKey
selector:@selector(doSomething:object:change:)];

在执行上述操作的同一对象中,您可以拥有如下方法:

- (void) doSomething:(NSString *)keyPath 
object:(id)object
change:(NSDictionary *)change {

// do your thing
}

您可以拥有任意数量的“doSomething”类型方法。只要他们使用相同的参数(keyPath:object:change:),它就会成功。每个对象有一个调度程序,希望接收有关任意数量对象更改的任意数量的通知。

我喜欢它的地方:

  1. 每个类只能有一个 observeValueForKeyPath,但您可能想要观察几件事。自然的下一个想法是“嘿也许我可以传递一个选择器”
  2. 哦,但是除非使用像 NSNotification 这样的包装对象,否则不可能通过 performSelector 传递多个参数。谁想要清理包装对象。
  3. 当父类(super class)也使用 KVO 时,覆盖 observeValueForKeyPath 会使任何通用方法变得困难 - 您必须知道哪些通知要传递给父类(super class)以及要保留哪些通知。
  4. 谁愿意在每个对象中重新实现相同的基于选择器的通用observeValueForKeyPath?最好只做一次并重复使用。

一个不错的变体可能是向 KVODispatcher 添加另一个字段,例如 id extraContext ,并在 objc_msgSend 调用中传递该 extraContext 对象。使用它来存储在观察到的数据发生变化时需要更新的 UI 对象可能很有用。甚至可能是一个 NSArray。

关于cocoa - 需要一些有关 Cocoa MVC/KVO 模式的提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4324036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com