xcode Swift 希望将#selector 的参数暴露给 Objective-C

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36962854/
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-09-15 08:46:37  来源:igfitidea点击:

Swift wants argument of #selector to be exposed to Objective-C

iosobjective-cxcodeswift

提问by Jason

I have a Swift project where I want to attach a method to a UIButton's tap event. I have the following code:

我有一个 Swift 项目,我想将一个方法附加到 UIButton 的点击事件。我有以下代码:

class MyClass {
  let myButton = UIButton(frame: CGRectMake(50, 50, 100, 50))
  init() {
    myButton.addTarget(self, #selector(self.didTap(_:)), forControlEvents: .TouchUpInside)
  }

  func didTap(sender: UIButton) {
    print("Tapped")
  }
}

XCode highlights my addTargetline and says:

XCode 突出显示我的addTarget行并说:

Argument of '#selector' refers to a method that is not exposed to Objective-C

If I add the @objcprefix to my func didTaplike it suggests then everything works fine.

如果我将@objc前缀添加到我的func didTap喜欢它建议然后一切正常。

Do I have something enabled in my build settings which is causing this strange behaviour?

我的构建设置中是否启用了导致这种奇怪行为的某些内容?

PS. I get this behaviour in 7.3.1. But if I try this in 7.2.1 it doesn't accept the #selector(method(_:))syntax, and Selector("method:")works fine.

附注。我在 7.3.1 中得到了这种行为。但是如果我在 7.2.1 中尝试这个,它不接受#selector(method(_:))语法,并且Selector("method:")工作正常。

回答by Darren

Selectors are a feature of Objective-C and can only be used with methods that are exposed to the dynamic Obj-C runtime. You can't have a selector to a pure Swift method.

选择器是 Objective-C 的一个特性,只能与暴露给动态 Obj-C 运行时的方法一起使用。你不能有一个纯 Swift 方法的选择器。

If your class inherits from NSObjectthen its public methods are exposed to Obj-C automatically. Since your class does not inherit from NSObjectyou have to use the @objcattribute to indicate that you want this method exposed to Obj-C so that it may be called with an Obj-C selector.

如果您的类继承自NSObject其公共方法,则会自动向 Obj-C 公开。由于您的类不是继承自NSObject您必须使用该@objc属性来指示您希望将此方法公开给 Obj-C,以便可以使用 Obj-C 选择器调用它。

#selector()is the new syntax in Swift 2.2. It allows the compiler to check that the selector you're trying to use actually exists. The old syntax is deprecated and will be removed in Swift 3.0.

#selector()是 Swift 2.2 中的新语法。它允许编译器检查您尝试使用的选择器是否确实存在。旧语法已弃用,并将在 Swift 3.0 中删除。

回答by matt

If I add the @objc prefix to my func didTaplike it suggests then everything works fine.

Do I have something enabled in my build settings which is causing this strange behaviour?

如果我didTap像建议的那样将 @objc 前缀添加到我的 func ,那么一切正常。

我的构建设置中是否启用了导致这种奇怪行为的某些内容?

No. What you're seeing is normal. Selectors are an Objective-C feature, and so is using a selector to send a message to your class instance. The only way Objective-C can send that message is if it can see either your class or the method itself. MyClass is not itself derived from NSObject, so Objective-C can't see it. So if you don't want to derive it from NSObject, you at least have to expose the method to Objective-C by marking it with @objc.

不,你看到的是正常的。选择器是一个 Objective-C 特性,因此使用选择器向类实例发送消息。Objective-C 可以发送该消息的唯一方法是它是否可以看到您的类或方法本身。MyClass 本身不是从 NSObject 派生的,所以 Objective-C 看不到它。所以如果你不想从 NSObject 派生它,你至少必须通过标记它来将方法暴露给 Objective-C @objc

and Selector("method:") works fine

和 Selector("method:") 工作正常

In earlier versions of Swift, the compiler would not help you in this situation, so your code would compile. But you would have crashed when the message arrived and Objective-C couldn't find the method. The whole point of the #selectorsyntax is to help you avoid that crash. And that's just what it did!

在早期版本的 Swift 中,编译器在这种情况下不会帮助你,所以你的代码会编译。但是当消息到达并且Objective-C 找不到该方法时,您会崩溃。在整点#selector语法是帮助您避免崩溃。而这正是它所做的!

回答by Fry

You have to subclass from NSObject

你必须从NSObject