ios 什么时候在 Swift 中使用 @objc?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30795117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 06:23:37  来源:igfitidea点击:

When to use @objc in Swift?

iosobjective-cswiftselectorprivate

提问by Wingzero

In Swift, I see some methods like:

在 Swift 中,我看到了一些方法,例如:

@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)

I was wondering, when to use @objc? I read some documents, but they are saying when you want it to be callable in Objective-C, you should add @objc flag

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

However, this is a private function in Swift, what does the @obj do?

但是,这是 Swift 中的私有函数,@obj 有什么作用?

采纳答案by Reming Hsu

private mean it visible only in Swift. so use @objc to visible in Objective-C. If you have a func to selector a private func in swift, it is required.

private 意味着它只在 Swift 中可见。所以使用@objc 在Objective-C 中可见。如果您有一个 func 可以在 swift 中选择一个私有 func,则它是必需的。

The @objc attribute makes your Swift API available in Objective-C and the Objective-C runtime.

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

See: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

请参阅: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

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

回答by Charles Srstka

Another late answer, but none of the existing answers on this question really answer the OP's question, which is: why the heck would you need to use @objcon a privateclass member, if @objcis there for interaction with Objective-C, and the member in question is private, meaning that even if you have Objective-C code in your project, it shouldn't be able to see the member anyway?

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

The reason is that, because many of the frameworks are written in Objective-C, sometimes Objective-C features are needed to interact with certain APIs.

原因是,由于许多框架是用 Objective-C 编写的,有时需要 Objective-C 特性来与某些 API 交互。

For example, suppose I want to register for a notification via DistributedNotificationCenter:

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

DistributedNotificationCenter.default.addObserver(self,
                                                  selector: #selector(somethingHappened(_:)),
                                                  name: someNotification,
                                                  object: nil)

For this to work, we need to be able to get the selector for the somethingHappenedmethod. However, selectors are an Objective-C concept, so if the method is not visible to Objective-C, it does not have a selector. Therefore, even if the method is private and should not be called by arbitrary outside code, it will need an @objcin order for the DistributedNotificationcode, which is written in Objective-C, to be able to call it via its selector.

为此,我们需要能够获取该somethingHappened方法的选择器。然而,选择器是一个 Objective-C 的概念,所以如果该方法对 Objective-C 不可见,它就没有选择器。因此,即使该方法是私有的并且不应由任意外部代码调用,它也需要一个@objc,以便DistributedNotification用 Objective-C 编写的代码能够通过其选择器调用它。

Another common case where @objcis needed is to support Key-Value Coding (KVC), especially on macOS, where KVC and KVO are used to implement Cocoa Bindings. KVC is, like many other systems in Cocoa, implemented in Objective-C, which has the effect of requiring KVC-compliant properties to be exposed to the Objective-C runtime. Sometimes, it makes sense for KVC-compliant properties to be private. One example is when you have a property that affects other properties:

另一个@objc需要支持的常见情况是支持键值编码 (KVC),尤其是在 macOS 上,其中 KVC 和 KVO 用于实现 Cocoa 绑定。KVC 与 Cocoa 中的许多其他系统一样,是在 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) }

In this case, our actual stored property is private, but the dependent property, which we doexpose to outside code, needs to send its notifications when the private property is updated. By marking the private property as @objc, we can easily do that by setting up a KVC dependency—otherwise, we'd have to write code to manually send the notifications in the private property's willSetand didSethandlers. In addition, the static property that informs the KVC system that dependentPropertyis dependent on originalPropertyneeds to be exposed to Objective-C so that the KVC system and find it and call it, but it's not relevant to clients of our code.

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

Also, a view controller in a macOS app that updates controls in its view using Cocoa Bindings as an implementation detail may make certain private properties KVC-compliant in order to bind those controls to them.

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

So as you see, there are times when a method or property may need to be exposed to Objective-C in order to interact with the frameworks, without necessarily needing to be visible to clients of your code.

因此,如您所见,有时可能需要将方法或属性暴露给 Objective-C 以与框架交互,而不必对代码的客户端可见。

回答by 0yeoj

@objc/ dynamic

@objc/动态

It's for compatibility: Once you import your Swift file/code into Objective-C based project.

这是为了兼容性:一旦您将 Swift 文件/代码导入到基于 Objective-C 的项目中。

And use that if you want your property/method to be accessed by Objective-C code or class.

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

Most of the time it happens when you are sub classing a Swift class of Objective-C base class.

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

A Swift class or protocol must be marked with the @objcattribute 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.

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

Here apple documentation that says about @objc.

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

Using Swift from Objective-C

从 Objective-C 使用 Swift

Language Interoperability Compatibility

语言互操作性兼容性

Links Updated:
Looks like the links has been updated by apple.

链接更新:
看起来链接已被苹果更新。

回答by Fraser

@objc is a class attribute, so you use

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

@objc public class MyClass

It exposes the class' methods to Objective C classes, so you'll only use it if your class contains public functions

它将类的方法公开给 Objective C 类,因此只有在类包含公共函数时才使用它

回答by BHendricks

A late answer, but this @objcbehavior is changing slightly as of Swift 4 (which came out in Xcode 9, which was generally released 10 days ago).

一个迟到的答案,但从@objcSwift 4(它在 Xcode 9 中出现,通常在 10 天前发布)开始,这种行为略有改变。

In Swift 4, some inference cases of @objcare removed. This just means in some additional cases where before the @objcheader was inferred by the Swift compiler, it's in Swift 4 not inferred.

在 Swift 4 中,@objc删除了一些推理情况。这只是意味着在一些额外的情况下,在@objcSwift 编译器推断出头文件之前,它在 Swift 4 中没有被推断出来。

Read more at the Swift evolution proposal about this change

在 Swift 进化提案中阅读有关此更改的更多信息

As has been mentioned, in general @objcis to expose certain methods to the Objective-C runtime, which is part of Swift's interoperability the language.

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

回答by yoAlex5

@objcexposes a declaration to Objective-C runtime. Let's take a look at #selectorfeature of Swift to use an Objective-C runtime. In this case you are able to define your Swift @objc private func[More]

@objc向 公开声明Objective-C runtime。让我们来看看#selectorSwift 使用 Objective-C 运行时的特性。在这种情况下,您可以定义您的 Swift @objc private func[更多]

To use Swift's functions from Objective-C:

在 Objective-C 中使用 Swift 的函数:

  1. Swift's class should be extended from NSObject
  2. Mark Swift's:

    a. @objcMembersclassonly - to expose allpublicconstructors, fieldsand methods. Also it is applicable for subclasses

    b. @objcclass/enum/protocol(except struct)[Named Type]

    • @objcclass(optional) - to expose a defaultpublic init(). Or @objc(<custom_name>)to setup a custom name for class.
    • @objcconstructors, fieldsand methods- to expose them selectively
  1. Swift 的类应该从 NSObject
  2. 马克·斯威夫特:

    一种。仅限@objcMembers- 公开所有public构造函数字段方法。它也适用于子类

    @objc类/枚举/协议结构除外)[命名类型]

    • @objc(可选) - 公开默认的public init(). 或者@objc(<custom_name>)为类设置自定义名称。
    • @objc构造函数字段方法- 有选择地公开它们

Swift's method will be available by the next naming:

Swift 的方法将在下一个命名时可用:

<swiftName>With<firstArgument>:<secondArgument>:

For example:

例如:

public func printHelloWorld(arg1: String, arg2:String)
//is reached through: 
[someObject printHelloWorldWithArg1: arg2:];

[@objcand dynamic]

[@objcdynamic]