我经常发现自己编写的“实用程序”类可以在整个项目中重复使用。
例如,假设我有一个“地址簿”视图。我可能想使用我的地址簿来选择向谁发送电子邮件,或者可能是谁被添加到会议请求中。
我开发了这个视图控制器,因此它可以被电子邮件控制器和会议控制器使用,具有某种回调机制,让调用者知道用户已完成从地址簿中选择某人,或者他们是取消。
在这种情况下,似乎基本上有四种(合理的)方法;
在AddressBookController上创建“AddressBookDelegate”协议和相应的委托属性。然后使用协议中定义的消息来传达结果(类似于UIActionSheetDelegate)。
在AddressBookController上创建一个“非正式”“AddressBookDelegate”协议和相应的委托属性,但委托属性的类型将为“id”,并将在运行时使用“respondsToSelector:”进行检查以查看是否委托实现了我们需要的方法(似乎大多数框架的东西都是以这种方式开始的)。
将AddressBookController传递给代表委托的id,以及两个SEL,用于指定用户选择用户或取消请求时要调用的方法。我看到的好处是;假设一个控制器支持同时发送电子邮件和设置会议(我知道在这个例子中看起来好像设计不好......但可以想象一个更通用的情况,这对于实用程序类来说似乎是完全合理的) - 在这种情况下你可以传递AddressBookController不同的SEL,具体取决于您是将用户添加到电子邮件中,还是将用户添加到会议中...相对于iVar的巨大改进,以指示控制器的“状态”。
传递AddressBookController两个块;一个在用户从地址簿中选择某人时运行,另一个在用户取消请求时运行。
块对我来说非常有用,而且更加优雅,我发现自己几乎不知道何时不使用它们。
我希望StackOverflow社区中更有经验的成员能够帮助他们解决这个问题。
答案 0 :(得分:27)
执行此操作的“传统”方法是使用协议。在将@protocol添加到语言之前使用了非正式的,但这是在我的时间之前,并且至少在过去的几年里,不鼓励使用非正式协议,特别是考虑到@optional说明符。至于通过两个SEL的'委托',这似乎比宣布一个正式的协议更难看,而且对我来说似乎并不合适。块是非常新的(特别是在iOS上),随着这些事情发生,虽然我们还没有看到大量的文档/博客上最好的尝试和真实的风格,我喜欢这个想法,这似乎是一个事物块最适合:整洁的新控制流结构。
基本上我想说的是这些方法中的每一种都有不同的年龄,没有一种比上一种更好,除了风格,这显然是非常重要的,并且最终为什么这些东西都被创造了。基本上,请选择您认为最新的东西,它应该是块或正式协议,并且您的混淆最有可能来自阅读冲突的来源,因为它们是在不同时间编写的,但是从时间上看,它是清楚地看到哪些取代了其他人。
[Controller askForSelection:^(id selection){
//blah blah blah
} canceled:^{
//blah blah blah
}];
可能比定义两个额外的方法,一个协议(正式或其他)或传递SEL并将它们存储在ivars等中更简洁。
答案 1 :(得分:17)
我会选择你的第一种方法。它在Cocoa中是一个久经考验的模式,似乎非常适合你正在做的事情。
关于其他方法的一些评论:
@optional
方法以来,非正式协议的效用要小得多。-awakeFromNib
(或其他)方法会非常大。在这种情况下,个别方法似乎更合适。但是,如果您确定自己永远不会超越两种方法,那么块方法似乎更合理。