【问题标题】:Objective-C/Cocoa: Proper design for delegates and controllersObjective-C/Cocoa:代理和控制器的正确设计
【发布时间】:2009-05-04 16:30:06
【问题描述】:

考虑以下常见情况:

您的 Cocoa 应用程序中有一些 MainView,从一个由 MainViewController 控制的 NIB 加载。您的MainView 包含一些控件,例如UILabel infoLabel。您还有一个代表MyDelegate 类,它接收某种事件。

您希望确保当MyDelegate 收到它的事件时,infoLabel 会得到适当的更新。但是,问题在于MyDelegate 没有对MainViewMainViewController 的引用,也不知道标签。

一种解决方案是将MainViewController 引用传递给委托对象,但这感觉不对,因为您可能会发现自己处于对象具有彼此引用的不良情况。

解决这个问题的正确设计是什么?

【问题讨论】:

  • 我现在遇到同样的问题。我们的解决方案是引用。你说这是一个不受欢迎的情况。你能解释一下原因吗?
  • 对我来说,主要有两个原因:循环引用“感觉”不对;你倾向于不断地投射参考。我可能完全不在了。
  • 我知道你的意思。我期待其他人对此的看法。好问题。

标签: objective-c cocoa touch


【解决方案1】:

在一个未具名的开发者论坛中,有人写道:

所以,长话短说,我决定开始使用 NSNotifications。人们一直在关注的斯坦福在线课程是由两名苹果工程师教授的。他们刚刚明确表示不要使用应用程序委托或全局变量,并表示要使用 NSNotifications、委托和 K-V 观察。

如果苹果工程师是这么说的,我会朝着那个方向前进。

NSNotifications 非常巧妙,因为它们不会真正干扰封装。侦听器只侦听通知和对象 - 我认为它不必知道或关心是谁发送的。

因此,在您的示例中,我会考虑让代表发布标签已更改的通知,或者如果可能的话,最好让控制器观察该属性。

【讨论】:

  • 我真的要去看斯坦福的视频了。
  • 虽然 NSNotifications 在这种情况下工作得很好,但我强烈建议不要在你的应用程序中使用太多。通知很难调试,你不一定只看你的代码就知道什么时候和什么地方被触发了。只是一些警告。
  • 嗨,马特,我了解您对 NSNotifications 的担忧。鉴于此,还有其他建议吗?
  • 对于这种情况,如果两个类有任何理由不能直接了解彼此,那么发布和监听 NSNotifications 可能是一个不错的途径。我的意图不是阻止它们的使用(天知道我在我的代码中大量使用它们),而是建议不要过度使用它们。
  • Jake:差不多 2 年后,我想知道这是否仍然是 Apple 在委托与通知方面的立场。另外,那是斯坦福的哪一集?
【解决方案2】:

我想到了以下 2 个选项:

  • 如果要委托的事件是由您的控制器发送的,您可以让该方法向控制器返回一个值以推送到视图。

  • 您还可以将 infoLabel 的值绑定到某个键(例如,使用 Cocoa 绑定或仅使用原始键值观察)。绑定对象(可以是委托或其他模型对象)可以只更新绑定键,这会将值推送到 infoLabel。例如,您可以将委托的“info”成员绑定到 infoLabel 的值。当代理接收到一个事件时,它可以更新信息成员,并且视图发生变化。实际绑定本身可能发生在 IB 中(如果您的委托在 nib 中)或控制器(它具有对视图和委托的引用)。

后一种解决方案基本上是循环引用,但对我来说似乎更干净。

【讨论】:

  • 是的,这无疑是迄今为止最干净的解决方案。
【解决方案3】:

我们实现了一个棘手的“数据”对象,它几乎可以控制一切。它检查是否有更改并保持所有全局变量的更新。

在创建新实例时,我这样引用 Data 类:

[[Button alloc] initWithData:data]];

data 是单例数据类。现在我们可以检查是否需要做出响应的更改。

我承认,它仍然需要像你描述的那样引用。似乎没有嵌入简单的parent 引用。

【讨论】:

    【解决方案4】:

    如您所说,通常的模式是通过其委托方法传递指向MainView 的指针。因此,如果 MainView 正在调用其委托的 doSomethingWithFoo: 方法,您希望将该方法更改为:

    - (void)mainView:(MainView *)view doSomethingWithFoo:(id)foo
    

    并相应地调用新方法。如果直接操作MainView指针,循环引用应该没有问题。

    【讨论】:

    • 但是假设委托不是MainView的委托,而是其他协议的委托...?
    • 那么使用协议中指定的方法呢?它正在接收来自 MainView 的一些通知,对吧?也许问题中缺少某些与情况相关的方面。
    • 假设我设置了一个实现 CLManagerDelegate 协议(Cocoa Touch)并监听位置更新的对象。它不接收来自 MainView 的通知,但需要访问标签。
    • 好吧,看来我误解了“委托对象”的含义。只是下次的建议,如果它实际上是相关对象的委托,您只想将其称为委托。如果我有一个类TextController,它是UITextField 的代表,并且我在谈论应用程序中的其他一些控件,我不会在该上下文中将TextController 称为代表。一个应用程序中可以有无限的“代表”,而这个词本身几乎没有意义。作为代表对于什么实例/类是有意义的上下文。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 2011-01-05
    • 2013-08-15
    • 2011-01-24
    相关资源
    最近更新 更多