简体   繁体   English

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

[英]How to use Struct as Observer in NotificationCenter

In NotificationCenter Class , Why apple has created Observer of type Any? 在NotificationCenter Class中,为什么苹果创建了Any类型的Observer?

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

My Reasoning. 我的推理。

  1. If observer is struct then on assigning inside as function parameter, It will be copied then how my observer can receive the notification. 如果观察者是struct,则在将内部分配为函数参数时,它将被复制,然后观察者将如何接收通知。
  2. I can't write any function which uses @objc prefix in Struct. 我无法在Struct中编写任何使用@objc前缀的函数。
  3. Selector is always be type of @objc. 选择器始终是@objc的类型。

So What is the use of Any in addObserver..... It should always be of type AnyObject. 那么addObserver中Any的用途是什么。它应该始终是AnyObject类型。

Secondly we already known that NotificationCenter keep the weak copy of observer, And we can't use weak modifier for type Any. 其次,我们已经知道NotificationCenter保留了观察者的弱副本,并且我们无法对Any类型使用弱修饰符。 Then how apple is managing all this? 那么苹果如何管理所有这一切?

Any help in understanding this concept is highly appreciated. 非常感谢您理解此概念。

No one chose to make this parameter Any . 没有人选择将此参数设置为Any It's just what they got by default. 这就是他们默认情况下得到的。 It's automatically bridged from ObjC: 它是从ObjC自动桥接的:

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

The default way that id is bridged is Any . 桥接id的默认方式是Any It hasn't been specially refined for Swift. 它尚未针对Swift进行专门改进。 In practice, you can't really use structs meaningfully here. 实际上,您不能在这里真正有意义地使用结构。 The fact that the compiler won't stop you from calling it in an unhelpful way doesn't imply that it's intended to be used that way. 编译器不会阻止您以无用的方式调用它的事实并不意味着它打算以这种方式使用。

Why type Any? 为什么输入Any? - because in Objective C it is type id . -因为在Objective C中它是id类型。

Why you can't mark your function as @obj - @obc is the keyword for Swift code which indicates what compiler should add this method to a header file for this Class , yes you can make headers only for Classes . 为什么不能将函数标记为@obj @obc是Swift代码的关键字,它指示什么编译器应将此方法添加到此Class的头文件中,是的,您只能为Classes制作头。

Selector also is the objective-c term, it just says which function to invoke, similar to msg_send 选择器也是Objective-C术语,它只说要调用哪个函数,类似于msg_send

In NotificationCenter Class , Why apple has created Observer of type Any. 在NotificationCenter Class中,为什么苹果创建了Any类型的Observer。

Because all Objective-C id declarations are translated into Swift as Any. 因为所有的 Objective-C id声明都被翻译成Swift as Any。

You might object that this really should be AnyObject, because only a class will work here. 您可能会反对说这实际上应该是AnyObject,因为这里只有一个类可以工作。 And indeed, that's the way id used to be translated into Swift. 实际上,这就是id过去被转换为Swift的方式。 But nowadays you can pass anything where an id is expected, because if it's something Objective-C can't understand, it will be boxed up as a class instance (eg as a _SwiftValue ) so that it can make the round-trip into Objective-C and back again to Swift. 但是如今,您可以传递任何需要id的东西,因为如果它是Objective-C无法理解的,它将被包装为一个类实例(例如,作为_SwiftValue ),以便可以将其往返于Objective -C然后再次回到Swift。 Therefore id is translated as Any. 因此, id被翻译为Any。

However, just because you can pass a struct here doesn't mean you should. 但是,仅仅因为您可以在此处传递结构并不意味着您应该这样做。 It won't work, as you've discovered. 正如您所发现的,它不起作用。 Objective-C cannot introspect a Swift struct. Objective-C无法自检Swift结构。

There are lots of situations like this, where Cocoa gives you enough room to hang yourself by passing the wrong thing. 很多情况下,可可都通过传递错误的东西给您足够的空间来吊死自己。 The contents of a CALayer is typed as Any, but if you pass anything other than a CGImage, nothing will happen. CALayer的contents键入为Any,但是如果您传递的不是CGImage,则什么都不会发生。 The layerClass if a UIView is typed as AnyClass, but you'd better pass a CALayer subclass. layerClass如果一个UIView的类型是AnyClass,但你最好通过一个CALayer的子类。 I could go on and on. 我可以继续下去。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM