题
我们正在开发一个定制EventEmitter启发在Objective-C消息系统。 对于听众提供回调,我们应要求块或选择 ,为什么?
你更愿意使用,作为一个开发者耗费了第三方库? 这似乎是最符合苹果的轨迹,指导方针和做法?
背景
我们正在开发一个全新的iOS SDK Objective-C中哪些其他第三方将使用嵌入功能集成到他们的应用程序。 我们的SDK的一个重要组成部分,需要事件监听器的通信。
有五种模式,我知道这样做在Objective-C的回调,其中三个不适合:
- NSNotificationCenter -不能使用,因为它不保证顺序观察员将得到通知,并因为没有办法观察员,以防止其他观察者接收事件(如
stopPropagation()
在JavaScript中)。 - 键-值观察 -似乎是一个很好的架构配合并不因为我们真正拥有的是信息传递,并不总是“国家”的约束。
- 代表和数据源 -在我们的情况下,通常会有许多听众,没有一个可能理所当然地被称为委托。
而其中两个是竞争者:
- 选择器 -在这种模式下,呼叫者提供一个选择器和被共同调用来处理事件的靶。
- 块 -在IOS 4引入块允许功能周围没有束缚于像观察者/选择图案的物体通过。
这似乎是一个深奥的意见的问题,但我觉得有一个客观的“正确”的答案,我在Objective-C,以确定的确非常缺乏经验。 如果有更好的StackExchange网站这个问题,请通过移动它那里帮助我。
更新#1 - 2013年4月
我们选择块作为指定的回调,我们的事件处理程序的手段。 我们有这样的选择在很大程度上快乐和不打算去除基于块的听众的支持。 它确实有两个显着的缺点:内存管理和设计阻抗。
内存管理
块最容易在堆栈上使用。 通过将其复制到堆上创建长寿块介绍了有趣的内存管理问题。
块,这使得在包含对象方法的调用隐含地提高self
的引用计数。 假设你有对二传手name
类的属性,如果你叫name = @"foo"
一个块中,编译器将这种情况视为[self setName:@"foo"]
并保留self
,这样它不会释放而块仍然存在。
实现一个EventEmitter是指具有长寿命的块。 为了防止隐性保留,发射器的用户需要创建一个__block
参考self
块,前外:
__block *YourClass this = self;
[emitter on:@"eventName" callBlock:...
[this setName:@"foo"];...
}];
这种方法唯一的问题是, this
被调用的处理之前,可能被释放。 因此,被释放时,用户必须注销他们的听众。
设计阻抗
有经验的Objective-C开发人员希望使用熟悉的模式库进行互动。 委托是一个非常熟悉的模式,等规范的开发人员期望使用它。
幸运的是,委托模式和基于块的听众不是相互排斥的。 虽然我们的发射器必须能够从许多地方(有一个代表将无法正常工作),我们仍然可以公开的接口,这将允许仿佛他们班是委托开发商与发射器进行交互处理的听众。
我们还没有实现这个,但我们可能会根据来自用户的请求。
更新#2 - 2013年10月
我不再工作对催生这一问题的项目,具有相当愉快地回到了我的JavaScript的故土。
聪明的开发商谁接手这个项目的正确决定完全退休,我们的基于块的定制EventEmitter。 而即将发布的已切换到ReactiveCocoa 。
这使他们比以前给予我们的EventEmitter库更高级别的信令模式,并允许它们封装信号处理比我们的基于块的事件处理程序或类级别的方法做了更好的内部状态。