2

我可以使用一些架构建议。我几次遇到以下问题,我从来没有找到一个真正优雅的方法来解决它。NSNotifications vs代表同一协议的多个实例

的问题,在尽可能高的级别描述:
我有一个想充当委托多个子(都使用相同的协议)一个父类,但是当孩子们叫父方法,父母不再知道哪个孩子正在打电话。

我想使用松耦合(委托/协议或通知),而不是直接调用。我不需要多个处理程序,所以通知看起来可能会过度。

为了说明问题,让我尝试超简化的示例
予先从父视图控制器(和对应的图)。我创建了三个子视图并将它们中的每一个插入到父视图中。我希望父视图控制器在用户触摸其中一个孩子时得到通知。有几个选项可以通知父代:

  1. 定义一个协议。父母实现协议并将其自身设置为每个孩子的代表。当用户触摸子视图时,其视图控制器调用其委托(父)。在这种情况下,父母被通知视图被触摸,但它不知道哪一个。还不够好。

  2. 与#1相同,但定义协议中的方法也传递某种标识符。当孩子告诉其代表被触动时,它也会传递一个指向自己的指针。通过这种方式,父母确切知道哪个视图被触动。对一个对象传递自己的引用看起来很奇怪。

  3. 使用NSNotifications。父母为三个孩子中的每一个定义了一个单独的方法,然后为三个孩子中的每个孩子订阅“viewWasTouched”通知作为通知发送者。孩子们不需要附加自己的用户字典,但他们确实需要发送一个指向他们自己的指针作为范围的通知。

  4. 与#4相同,但不是使用单独的方法,父母可以仅使用一个开关盒或其他分支以及通知的发件人来确定要采用哪条路径。

  5. 创建多个充当子视图委托的中间类,然后通过指向子项的指针或其他区分因子调用父项的方法。这种方法似乎不可扩展。

这些方法中的任何一种都被认为是最佳实践吗?我不能肯定地说,但感觉就像我错过了更明显/优雅的东西。

回答

5

您的#2是代表的标准可可模式。委托协议的每条消息都将该对象作为第一个参数。例如,在UITableViewDelegate,你会发现这样的方法:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; 

当表视图将此消息发送到它的代表,它发送本身(表视图)作为第一个参数。如果委托对象是多个表视图的委托,它可以使用第一个参数来确定哪个表视图发送了消息。

当没有其他参数,该消息仍然采取了对象作为参数,如本UITableViewDataSource方法:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 

你会发现这个模式遍布在Cocoa Touch框架; UIPickerViewDelegateUIImagePickerControllerDelegateUINavigationControllerDelegate只是几个例子。

你应该遵循标准模式,除非你有一个令人信服的理由不要。遵循这个约定会使其他人(和将来你)更容易理解你的代码。

+0

太棒了!我想我会滚动。 – 2012-07-11 04:32:49

+0

谢谢罗布。你能澄清'弄清楚'一点吗?在设置代表时,我是否应该存储子代码的地图?或者有没有一种标记风险投资的标准方式?我知道使用view.tag作为视图,但VC似乎没有用于此目的的等效属性。 – scipilot 2014-02-14 02:18:42

+0

我发现[这个问题](http://stackoverflow.com/questions/8660637/ios-uniquely-identify-viewcontrollers-from-storyboard)建议使用VC.view.tag这是有道理的,如果它没有被使用为其他任何事情。但我最后只是简单地存储了最后一个segue的名字,因为我只能一次显示一个孩子。 – scipilot 2014-02-14 04:10:22