什么是@objc属性
实战需求
在Swift中,我看到一些类似的方法:
@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)
默认情况下,Swift生成的代码仅对其他Swift代码可用,但是如果您需要与Objective-C运行时进行交互(例如,整个UIKit),则需要告诉Swift该怎么做。
这就是@objc属性的来源:当您将其应用于类或方法时,它会指示Swift将这些内容提供给Objective-C和Swift代码。因此,每次您要从a UIBarButtonItem或a 调用方法时Timer,都需要使用标记该方法,@objc以便将其公开-所有这些以及许多其他都是Objective-C代码。
不用担心:如果您忘记了@objc在需要时添加代码,则代码根本就不会编译–这不是您偶然会忘记并引入bug的东西。
要将方法公开给Objective-C,只需@objc在其名称之前编写如下:
class MyController: UIViewController {
@objc func authenticateUser() {
}
}
整个类自动继承自Objective-C,因为它是从Object-C继承而来的UIViewController,但是如果需要,您也可以通过将其标记为Object-C来显式地使类开放@objc。
实战例子
例如,假设我想通过注册一个通知DistributedNotificationCenter:
DistributedNotificationCenter.default.addObserver(self,
selector: #selector(somethingHappened(_:)),
name: someNotification,
object: nil)
为此,我们需要能够获取somethingHappened方法的选择器。但是,选择器是Objective-C的概念,因此,如果该方法对于Objective-C不可见,则它没有选择器。因此,即使该方法是私有的,并且不应被任意外部代码调用,它也需要一个@objc使DistributedNotification使用Objective-C编写的代码才能通过其选择器调用的方法。
另一个@objc需要的常见情况是支持键值编码(KVC),尤其是在macOS上,其中KVC和KVO用于实现可可绑定。就像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处理程序中手动发送通知。另外,通知dependentProperty依赖于KVC系统的静态属性originalProperty需要暴露给Objective-C,以便KVC系统找到并调用它,但它与我们代码的客户端无关。
此外,使用可可绑定作为实现细节更新其视图中的控件的macOS应用程序中的视图控制器可以使某些私有属性符合KVC,以便将这些控件绑定到它们。
因此,正如您所看到的,有时可能需要将方法或属性公开给Objective-C以便与框架进行交互,而不必一定要对代码的客户端可见。