SO告诉我这个问题是主观的,可能会被关闭。这确实是主观的,因为我要求经验丰富的Objective-C开发人员提出意见。我应该在其他地方张贴这个吗?请告知。
Objective-C相当新,尽管对编写OOP代码的概念非常有信心,但我从一开始就一直在努力应对NSNotification与Delegate的困境。我仅就这个问题发表了一些问题。我想,我确实得到了要点。通知在全球范围内广播,因此不应用于通知密切相关的对象。存在代表将任务移交给代表委托对象的其他对象。虽然这可以用于密切相关的对象,但我发现工作流程冗长(新类,新协议等),单独的“委托”一词让我想起了军队和老板,总的来说让我感到不安。 / p>
我来自哪里(AS3)有一些叫做事件的东西。他们在代表和NSNotifications之间走了一半,并且几乎统治了闪电通知的世界,直到最近,罗伯特·彭纳先生出现并表达了他对事件的不满。因此,他编写了一个现在广泛用于AS3社区的库,名为Signals。受Qt中的C#事件和信号/插槽的启发,这些信号实际上是对象的属性,您可以从外部访问并添加侦听器。你可以用信号做更多的事情,但就其核心而言,就是这样。
因为这个概念非常简陋,所以我试了一下,在Objective-C中编写了自己的信号类。 I've gisted Signal.h/.m here
使用它来通知A类中B类事件的A类的方法可能如下所示:
// In class b, assign a Signal instance to a retained property:
self.awesomeThingHappened = [[[Signal alloc] init] autorelease];
// In class a, owner of class b, listen to the signal:
[b.awesomeThingHappened add:self withSelector:@selector(reactToAwesomeThing)];
// And when something actually happens, you dispatch the signal in class b:
[self.awesomeThingHappened dispatch];
// You might even pass along a userInfo dictionary, your selector should match:
[self.awesomeThingHappened dispatchWithUserInfo:userInfo];
我希望它遵守正确的内存管理规则,但是当信号deallocs时,它应该自动删除所有侦听器并静默消失。像这样的信号不应该是通知和授权的通用替代品,但是有很多紧密的反制情况,我觉得Signal比其他两个更干净。
我对stackoverflow的问题是你怎么看待这样的解决方案?如果你的一个实习生把它放进去,你会立即从你的项目中删除吗?如果他已完成实习,你会解雇你的员工吗?或者可能已经有类似但更加宏伟的东西,你可以使用它?
感谢您的时间,EP。
编辑:让我举一个具体的例子,说明我在iOS项目中如何使用它。
考虑这种具有嵌套所有权的四种对象类型的场景。有一个视图控制器拥有一个窗口管理器,拥有几个窗口,每个窗口拥有一个带控件的视图,其中包含一个关闭按钮。这里可能存在设计缺陷,但这不是示例的重点:P
现在,当点击关闭按钮时,手势识别器会触发窗口对象中的第一个选择器。这需要通知窗口管理器它正在关闭。然后窗口管理器可以决定是否出现另一个窗口,或者窗口是否完全隐藏,此时视图控制器需要获得一个凸起以启用主视图上的滚动。
从窗口到窗口管理器,从窗口管理器到视图控制器的通知是我现在用Signals实现的。这可能是委托的情况,但对于“近距离”行动,创建两个委托协议似乎很冗长。另一方面,由于这些对象的耦合定义非常明确,因此NSNotifications似乎也不是这样。 KVO也没有真正的价值变化,因为它只是一个按钮。听取某种“隐藏”状态只会让我在重新打开窗口时重置该标志,这使得它更难理解并且容易出错。
答案 0 :(得分:2)
好吧,在对答案和评论进行腌制之后,我想我已经得出结论,我从AS3借来的Signal类,在Objective-C / Cocoa中几乎没有理由存在。 Cocoa中有几种模式涵盖了我想用Signal类覆盖的使用范围。对于经验丰富的Cocoa开发人员来说,这似乎是微不足道的,但对我而言,很难让频谱完整。
我试图把它简明扼要地说,但如果我错了,请纠正我。
仅用于通知您的应用程序用户交互(主要是触摸)。从我所看到和阅读的内容来看,没有办法“借用”目标行动系统供你自己使用
在可访问对象中的值更改时接收通知非常有用。对通知没有附加值的特定事件(如计时器事件或接口后续事件)不太有用。
非常有用,可以在值不可更改的对象中更改值或发生其他事件时接收通知。由于通知中心的广播性质,这不太适合对象直接引用另一个对象的情况。
与其他三个代码相比,占用的代码最多,但是当其他三个代码不同时,它也是最合适的。当一个对象应该被告知另一个对象中的特定事件时,请使用此对象。不应仅仅因为访问所有者对象的方法而滥用代表。坚持使用'应该','将'和'做'等方法。
这是一个有趣的实验,但我主要用于经典授权情况。我还用它来规避链接的代理(c代表b,b代表a,在哪里启动应该使它成为c的事件)而不想诉诸NSNotification。
我仍然认为应该有一个更优雅的解决方案,但现在我会 坚持现有的框架。如果有人有更正或其他通知概念,请告诉我。谢谢你的帮助!
答案 1 :(得分:1)
这是一个有趣的想法,但我想我看不出是什么让它与Cocoa的通知中心截然不同。比较和对比:
self.awesomeThingHappened = [[[Signal alloc] init] autorelease]; // Your signals library
// Cocoa notifications (no equivalent code)
[b.awesomeThingHappened add:self withSelector:@selector(reactToAwesomeThing)]; // Your signals library
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reactToAwesomeThing:)
name:@"AwesomeThingHappened"
object:n]; // Cocoa notifications
[self.awesomeThingHappened dispatch]; // Your signals library
[[NSNotificationCenter defaultCenter] postNotificationName:@"AwesomeThingHappened"
object:self]; // Cocoa notifications
[self.awesomeThingHappened dispatchWithUserInfo:userInfo]; // Your signals library
[[NSNotificationCenter defaultCenter] postNotificationName:@"AwesomeThingHappened"
object:self
userInfo:userInfo]; // Cocoa notifications
所以,好的。我不认为你想说的是,逐行,Cocoa的Signals库是不同的;相反,该论点认为它是耦合的术语,它不像代表那么紧,但不像通知那样松散。为此,我想我不知道它有多必要?我想我可以看到有必要说“这个对象'A'在很大程度上依赖于'B',但不需要紧密耦合”,但说实话,这似乎是一种罕见的情况。 / p>
无论如何,NSNotificationCenter
及其同类以及代表在Cocoa应用程序中都非常标准。我总是使用经验法则,如果你偏离标准,甚至是事实上的标准,你应该有充分的理由。如果您有充分的理由既不使用NSNotificationCenter
也不使用委托,那么您可能有充分的理由使用此信号设置。 (顺便说一句,我对将通知和代表联系起来犹豫不决 - 他们每个人都有一个角色并且因各种原因而存在。)
没有具体的用例,很难说更多。我倾向于说,“嘿,它以一种令人讨厌的方式看起来很酷,但看起来它已经填满了已经通知的角色。”您是否有任何具体的用例?
答案 2 :(得分:0)
您如何看待这样的解决方案?
我真的没看到有什么好处。对我而言,它似乎是目标/动作+通知的组合(您可以为单个通知事件设置多个目标/操作,但是t / a对已注册到对象本身而不是全局通知中心)。实际上,除了KVO仅限于可观察的属性之外,它更像是键值观察,但
如果你的一个实习生把它放进去,你会立即从你的项目中删除它吗?
没有。它不是坏代码。事实上,它似乎有点整洁。但我只是没有看到明显的好处。
如果他的员工已经完成实习,你会解雇他吗?
当然不是。你不会因为编写好的代码而解雇人。
是否可能已经有类似的东西,但你会使用更多的东西呢?
如果您真的想要做到这一点,请更改API以使用块。然后你可以这样做:
[object dispatchOnAwesomeThingHappened:^{
NSLog(@"holy cow, something awesome just happened!");
}];
然而,再一次,你只能对对象明确“发送”的内容做出反应。如果您可以在任意方法调用之前和/或之后立即附加内容,那将更加简洁。如果您对此感兴趣,那么我会查看Aspect Objective-C on github。
答案 3 :(得分:0)
我认为 是NSNotifications和Delegates之间的差距。和KVO has the worst API in all of Cocoa。
至于NSNotificationCenter
,这里有一些问题:
所以肯定需要更好的东西。
我创建了my own observable class,我在每个项目中使用它。另一种方法是使用ReactiveCocoa' RACSignal。