何时在swift代码中使用@objc?

Win*_*ero 74 private objective-c selector ios swift

我是swift的新手,我看到一些方法,如:

@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)
Run Code Online (Sandbox Code Playgroud)

我想知道什么时候使用@objc?我读了一些文档,但是他们说当你希望它在Objective-C中可以调用时,你应该添加@objc标志

但是,这是一个快速的私有函数,@ obj做了什么?

Rem*_*Hsu 56

私人意味着它只在Swift中可见.所以使用@objc在Objective-C中可见.如果你有一个func来选择swift中的私有函数,那么它是必需的.

@objc属性使您的Swift API在Objective-C和Objective-C运行时可用.

请参阅:https: //developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html

  • 链接中断。尤其是在 Apple 文档中。请考虑从此处的文档中提取关键元素。 (4认同)
  • 不确定这个答案如何正确并回答他的 Q。这里提供的答案已经在他的 Q 本身中“但是他们说当你希望它在 Objective-C 中可以调用时,你应该添加 \@objc 标志”,他的主要内容Q 是“这是 swift 中的私有函数,\@obj 有什么作用?” (2认同)

Cha*_*tka 48

另一个迟到的答案,但这个问题的现有答案都没有真正回答OP的问题,即:为什么你需要@objcprivate类成员上使用,如果@objc有与Objective-C的交互,以及有问题的成员是私有的,这意味着即使您的项目中有Objective-C代码,它也不应该能够看到该成员?

原因在于,由于许多框架都是用Objective-C编写的,因此有时需要Objective-C功能才能与某些API进行交互.

例如,假设我想通过以下方式注册通知DistributedNotificationCenter:

DistributedNotificationCenter.default.addObserver(self,
                                                  selector: #selector(somethingHappened(_:)),
                                                  name: someNotification,
                                                  object: nil)
Run Code Online (Sandbox Code Playgroud)

为此,我们需要能够获得somethingHappened方法的选择器.但是,选择器是Objective-C概念,因此如果Objective-C看不到该方法,则它没有选择器.因此,即使该方法是私有的,不应被任意的外部代码调用,它需要一个@objc为了使DistributedNotification代码,这是用Objective-C,能够通过其选择调用它.

需要的另一个常见情况@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) }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们的实际存储属性是私有的,但是我们确实向外部代码公开的依赖属性需要在更新私有属性时发送其通知.通过将私有属性标记为@objc,我们可以通过设置KVC依赖项轻松地做到这一点 - 否则,我们必须编写代码来手动在私有属性willSetdidSet处理程序中发送通知.此外,通知KVC系统dependentProperty依赖的静态属性originalProperty需要暴露给Objective-C,以便KVC系统找到并调用它,但它与我们代码的客户端无关.

此外,macOS应用程序中的视图控制器使用Cocoa Bindings作为实现细节更新其视图中的控件可能会使某些私有属性符合KVC,以便将这些控件绑定到它们.

如您所见,有时可能需要将一个方法或属性公开给Objective-C以便与框架交互,而不一定需要对代码的客户端可见.


0ye*_*eoj 24

@objc/动态

这是为了兼容性:将Swift文件/代码导入基于Objective-C的项目.

如果您希望Objective-C代码或类访问您的属性/方法,请使用它.

大多数情况下,当您对Swift类的Objective-C基类进行子类化时会发生这种情况.

必须使用@objc属性标记Swift类或协议才能在Objective-C中访问和使用.该属性告诉编译器可以从Objective-C访问这段Swift代码.如果您的Swift类是Objective-C类的后代,则编译器会自动为您添加@objc属性.

这里有关于的苹果文档@objc.

使用Objective-C中的Swift

语言互操作性兼容性

链接已更新:
看起来苹果已更新链接.


Fra*_*ser 10

@objc是一个类属性,所以你使用

@objc public class MyClass
Run Code Online (Sandbox Code Playgroud)

它将类方法公开给Objective C类,因此如果您的类包含公共函数,则只能使用它


BHe*_*cks 7

一个迟到的答案,但是这个@objc行为在Swift 4中有所改变(它在Xcode 9中出现,它通常在10天前发布).

在Swift 4中,@objc删除了一些推理案例.这只是在一些其他情况下,即在@objcSwift编译器推断出头之前,它在Swift 4中没有被推断.

阅读有关此更改的Swift evolution提案

正如已经提到的,通常@objc是将某些方法暴露给Objective-C运行时,这是Swift的语言互操作性的一部分.