什么时候在 Swift 中使用 @objc?
When to use @objc in Swift?
在 Swift 中,我看到一些方法,例如:
@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)
我想知道什么时候使用@objc?我读了一些文档,但他们说当你希望它在 Objective-C 中可调用时,你应该添加 @objc 标志
然而,这是Swift中的私有函数,@obj是做什么的?
@objc 是一个 class 属性,所以你使用
@objc public class MyClass
它将 class' 方法公开给 Objective C classes,因此只有当 class 包含 public 函数时才可以使用它
private 表示它仅在 Swift 中可见。
所以使用@objc 在 Objective-C 中可见。
如果您有一个函数来选择 swift 中的私有函数,则它是必需的。
The @objc attribute makes your Swift API available in Objective-C and the Objective-C runtime.
@objc / 动态
这是为了兼容性:将 Swift file/code 导入基于 Objective-C 的项目后。
如果您希望 Objective-C 代码或 class 访问您的 property/method,请使用它。
大多数情况下,当您 class 对 Objective-C 基础 class 的 Swift class 进行子 class 时,就会发生这种情况。
A Swift class or protocol must be marked with the @objc attribute to
be accessible and usable in Objective-C. This attribute tells the
compiler that this piece of Swift code can be accessed from
Objective-C. If your Swift class is a descendant of an Objective-C
class, the compiler automatically adds the @objc attribute for you.
这里是关于 @objc
.
的苹果文档
链接已更新:
看来苹果已更新链接。
一个迟到的答案,但是这个 @objc
行为在 Swift 4 中发生了轻微的变化(它出现在 Xcode 9 中,通常是在 10 天前发布的)。
在Swift4中,删除了@objc
的一些推理案例。这仅意味着在某些其他情况下,在 Swift 编译器推断 @objc
header 之前,它在 Swift 4 中未被推断。
阅读有关 this change
的 Swift 进化提案的更多信息
如前所述,通常 @objc
是将某些方法公开给 Objective-C 运行时,这是 Swift 语言互操作性的一部分。
另一个迟到的答案,但是 none 这个问题的现有答案确实回答了 OP 的问题,即:为什么你需要在 [=13= 上使用 @objc
] class 成员,如果 @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 公开方法或 属性 以便与框架交互,而不必对框架的客户可见你的代码。
@objc 对比@objcMembers
@objc
向 Objective-C runtime
. Let's take a look at #selector
[About] feature of Swift to use an Objective-C runtime. In this case you are able to define your Swift @objc private func
公开声明
要使用 Swift 来自 Objective-C 的功能:
- Swift的class应该从
NSObject
扩展
- 标记Swift的:
一个。仅 @objcMembers
class - 公开 all public
constructors、领域和方法。也适用于 subclasses
b。 @objc
class/enum/protocol(结构除外)[Named Type]
@objc
class(可选)- 公开一个 default public init()
。或 @objc(<custom_name>)
为 class. 设置自定义名称
@objc
构造函数、字段和方法 - 有选择地公开它们
Swift的方法将在下一个命名时可用:
<swiftName>With<firstArgument>:<secondArgument>:
例如:
public func printHelloWorld(arg1: String, arg2:String)
//is reached through:
[someObject printHelloWorldWithArg1: arg2:];
在 Swift 中,我看到一些方法,例如:
@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)
我想知道什么时候使用@objc?我读了一些文档,但他们说当你希望它在 Objective-C 中可调用时,你应该添加 @objc 标志
然而,这是Swift中的私有函数,@obj是做什么的?
@objc 是一个 class 属性,所以你使用
@objc public class MyClass
它将 class' 方法公开给 Objective C classes,因此只有当 class 包含 public 函数时才可以使用它
private 表示它仅在 Swift 中可见。 所以使用@objc 在 Objective-C 中可见。 如果您有一个函数来选择 swift 中的私有函数,则它是必需的。
The @objc attribute makes your Swift API available in Objective-C and the Objective-C runtime.
@objc / 动态
这是为了兼容性:将 Swift file/code 导入基于 Objective-C 的项目后。
如果您希望 Objective-C 代码或 class 访问您的 property/method,请使用它。
大多数情况下,当您 class 对 Objective-C 基础 class 的 Swift class 进行子 class 时,就会发生这种情况。
A Swift class or protocol must be marked with the @objc attribute to be accessible and usable in Objective-C. This attribute tells the compiler that this piece of Swift code can be accessed from Objective-C. If your Swift class is a descendant of an Objective-C class, the compiler automatically adds the @objc attribute for you.
这里是关于 @objc
.
链接已更新:
看来苹果已更新链接。
一个迟到的答案,但是这个 @objc
行为在 Swift 4 中发生了轻微的变化(它出现在 Xcode 9 中,通常是在 10 天前发布的)。
在Swift4中,删除了@objc
的一些推理案例。这仅意味着在某些其他情况下,在 Swift 编译器推断 @objc
header 之前,它在 Swift 4 中未被推断。
阅读有关 this change
的 Swift 进化提案的更多信息如前所述,通常 @objc
是将某些方法公开给 Objective-C 运行时,这是 Swift 语言互操作性的一部分。
另一个迟到的答案,但是 none 这个问题的现有答案确实回答了 OP 的问题,即:为什么你需要在 [=13= 上使用 @objc
] class 成员,如果 @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 公开方法或 属性 以便与框架交互,而不必对框架的客户可见你的代码。
@objc 对比@objcMembers
@objc
向 Objective-C runtime
#selector
[About] feature of Swift to use an Objective-C runtime. In this case you are able to define your Swift @objc private func
要使用 Swift 来自 Objective-C 的功能:
- Swift的class应该从
NSObject
扩展
- 标记Swift的:
一个。仅 @objcMembers
class - 公开 all public
constructors、领域和方法。也适用于 subclasses
b。 @objc
class/enum/protocol(结构除外)[Named Type]
@objc
class(可选)- 公开一个 defaultpublic init()
。或@objc(<custom_name>)
为 class. 设置自定义名称
@objc
构造函数、字段和方法 - 有选择地公开它们
Swift的方法将在下一个命名时可用:
<swiftName>With<firstArgument>:<secondArgument>:
例如:
public func printHelloWorld(arg1: String, arg2:String)
//is reached through:
[someObject printHelloWorldWithArg1: arg2:];