如何在NotificationCenter中将Struct用作观察者

时间:2019-06-30 16:36:51

标签: ios swift4 notificationcenter

在NotificationCenter类中,为什么苹果创建了Any类型的Observer?

func addObserver(Any, selector: Selector, name: NSNotification.Name?, object: Any?)

我的推理。

  1. 如果观察者是struct,则在将内部分配为函数参数时,它将被复制,然后观察者将如何接收通知。
  2. 我无法在Struct中编写任何使用@objc前缀的函数。
  3. 选择器始终是@objc的类型。

那么addObserver中Any的用途是什么..... 它应始终为AnyObject类型。

第二,我们已经知道NotificationCenter保留了观察者的弱副本,并且我们不能对Any类型使用弱修饰符。那么苹果如何管理所有这一切?

我们非常感谢您对理解这一概念的任何帮助。

3 个答案:

答案 0 :(得分:0)

没有人选择将此参数设为Any。这就是他们默认情况下得到的。它是从ObjC自动桥接的:

- (void)addObserver:(id)observer 
        selector:(SEL)aSelector
        name:(nullable NSNotificationName)aName
        object:(nullable id)anObject;

桥接id的默认方式是Any。它尚未针对Swift进行专门改进。实际上,您不能在这里真正有意义地使用结构。编译器不会阻止您以无用的方式调用它的事实并不意味着它打算以这种方式使用。

答案 1 :(得分:0)

为什么键入Any?-因为在目标C中键入id

为什么不能将函数标记为@obj-@obc是Swift代码的关键字,它指示什么编译器应将此方法添加到此 Class 的头文件中>,是的,您只能为课程创建标题。

选择器也是Objective-C的术语,它只是说出要调用的函数,类似于msg_send

答案 2 :(得分:0)

  

在NotificationCenter类中,为什么苹果创建了Any类型的Observer。

因为 all 个Objective-C id声明都被翻译成Swift,与Any一样。

您可能会反对说这确实应该是AnyObject,因为这里只有一个类可以工作。实际上,这就是id过去被翻译成Swift的方式。但是如今,您可以传递任何期望使用id的东西,因为如果Objective-C无法理解它,它将被装箱为一个类实例(例如,作为_SwiftValue),以便可以往返到Objective-C,然后再返回到Swift。因此id被翻译为Any。

但是,仅仅因为您可以在此处传递结构并不意味着您应该这样做。正如您所发现的,它不起作用。 Objective-C无法自检Swift结构。

在这种情况下,有很多,可可通过传递错误的东西为您提供了足够的空间来吊死自己。 CALayer的contents键入为Any,但是如果传递的不是CGImage,则什么都不会发生。 layerClass(如果UIView键入为AnyClass),但最好传递CALayer子类。我可以继续下去。