另一个迟到的答案,但这个问题的现有答案都没有真正回答 OP 的问题,即:如果有 @objc,为什么你需要在 private 类成员上使用 @objc用于与 Objective-C 的交互,并且所讨论的成员是私有的,这意味着即使您的项目中有 Objective-C 代码,它也不应该能够看到该成员?
原因是,由于许多框架是用 Objective-C 编写的,有时需要 Objective-C 特性来与某些 API 交互。
例如,假设我想通过DistributedNotificationCenter注册一个通知:
DistributedNotificationCenter.default.addObserver(self,
selector: #selector(somethingHappened(_:)),
name: someNotification,
object: nil)
为此,我们需要能够获得somethingHappened 方法的选择器。然而,选择器是一个 Objective-C 的概念,所以如果该方法对 Objective-C 不可见,它就没有选择器。因此,即使该方法是私有的并且不应被任意外部代码调用,它也需要一个@objc 以便用Objective-C 编写的DistributedNotification 代码能够通过其调用它选择器。
另一个需要@objc 的常见情况是支持键值编码 (KVC),尤其是在 macOS 上,其中 KVC 和 KVO 用于实现 Cocoa 绑定。与 Cocoa 中的许多其他系统一样,KVC 是在 Objective-C 中实现的,其效果是要求符合 KVC 的属性暴露给 Objective-C 运行时。有时,将符合 KVC 的属性设为私有是有意义的。一个例子是当你有一个影响其他属性的属性时:
@objc private dynamic var originalProperty: String
@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
#keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }
在这种情况下,我们实际存储的属性是私有的,但是我们向外部代码公开的依赖属性需要在私有属性更新时发送通知。通过将私有属性标记为@objc,我们可以通过设置KVC 依赖项轻松地做到这一点——否则,我们必须编写代码来手动发送私有属性的willSet 和didSet 处理程序中的通知。另外,通知KVC系统dependentProperty依赖于originalProperty的静态属性需要暴露给Objective-C,以便KVC系统找到并调用它,但它与我们代码的客户端无关.
此外,macOS 应用程序中的视图控制器使用 Cocoa 绑定作为实现细节更新其视图中的控件,可能会使某些私有属性符合 KVC 标准,以便将这些控件绑定到它们。
如您所见,有时可能需要将方法或属性暴露给 Objective-C 以便与框架交互,而不必对代码的客户端可见。