在 Swift 中使用选择器的正确方法
Proper way to use selectors in Swift
我正在以编程方式创建一个视图,并添加一个函数以便该操作响应 UIControlEvents.TouchUpInside 事件:
button.addTarget(self, action: action, forControlEvents:
UIControlEvents.TouchUpInside)
因此,通过查看文档,我将此操作添加为选择器:
#selector(ViewController.onRegularClick)
XCode接着投诉:
Argument of #selector refers to a method that is not exposed to
Objective-C
所以我必须设置处理函数:
@objc func onRegularClick(sender: UIButton)
有人可以通过引导我阅读文档来让这个菜鸟走上正确的方向,或者甚至给出一个简短的解释,在:
- 为什么我不能再简单地将函数名称字符串传递给操作?
- 遵循 Swift 方式的正确方法是什么?使用选择器 class?
- 为什么我们需要传递 @objc 关键字以及它如何影响函数?
谢谢!
- 嗯,这叫进化
当方法中有一些参数时,应该将选择器声明为:
let selector = #selector(YourClass.selector(_:))
如果选择器与调用者相同 class,您只能输入 #selector(selector(_:))
。 _:
表示接受一个参数。所以,如果它接受更多的参数,你应该做这样的事情:(_:, _:)
等等。
我发现 @objc
只有当函数声明为私有或对象不继承自 NSObject
时才需要
1:目前可以,但它会产生弃用警告。在 Swift
3 这将是一个错误,所以你应该尽快修复它。这个做完了
因为编译器无法检查仅使用 String if
该函数确实存在,如果它是一个有效的 Objective C 函数
可以在运行时动态解析。
2:这样做:
button.addTarget(self, action: #selector(MyViewControllerClass.buttonPressed(_:)), forControlEvents: UIControlEvents.TouchUpInside)
3: 通常你不必使用@objc 属性。我假设您的 class ViewController
(出于任何原因)不是从 UIViewController
派生的。如果它派生自 UIViewController
则还继承调用函数选择器所需的 ObjC 行为。
- why can't I no longer pass simply the function name String to the action?
不推荐使用字符串作为选择器,您现在应该写 #selector(methodName)
而不是 "methodName"
。如果 methodName() 方法不存在,您将得到一个编译错误——另一个 class 的错误在编译时被消除了。这对于字符串是不可能的。
- how is the proper way to implement this following the Swift Way? Using the Selector class?
你做对了:
button.addTarget(self, action: #selector(ClassName.methodName(_:)), forControlEvents: UIControlEvents.TouchUpInside)
- why do we need to pass the @objc keyword and how it affects the function?
在 Swift 中,通常的方法是在编译时绑定方法的调用和方法的主体(就像 C 和 C++ 那样)。 Objective C 在 运行 时间完成。所以在 Objective C 中你可以做一些在 Swift 中不可能的事情 - 例如可以在 运行 时间交换方法的实现(它被称为方法调配)。 Cocoa 旨在与 Objective C 方法一起使用,这就是为什么您必须通知编译器您的 Swift 方法应该以类似 Objective-C 的方式编译。如果您的 class 继承了 NSObject ,即使没有 @objc 关键字,它也会被编译成类似 ObjC 的风格。
对于 swift3.0 就像下面的代码一样:
yourButton.addTarget(self, action: #selector(yourButtonPressed), for: .touchUpInside)
和您的 ButtonPressed 方法
@IBAction func yourButtonPressed(sender:UIButton) {
// Do your code here
}
每个人的答案都很完美,但我有更好的方法。希望你们会喜欢。
fileprivate extension Selector {
static let buttonTapped =
#selector(ViewController.buttonTapped(_:))
}
...
button.addTarget(self, action: .buttonTapped, for: .touchUpInside)
此文件中的此处 private 将有助于仅在文件中显示 buttonTapped。
以编程方式
button.addTarget(self, action: #selector(returnAction), for: .touchUpInside)
// MARK: - Action
@objc private func returnAction(sender: UIButton) {
print(sender.tag)
}
我正在以编程方式创建一个视图,并添加一个函数以便该操作响应 UIControlEvents.TouchUpInside 事件:
button.addTarget(self, action: action, forControlEvents:
UIControlEvents.TouchUpInside)
因此,通过查看文档,我将此操作添加为选择器:
#selector(ViewController.onRegularClick)
XCode接着投诉:
Argument of #selector refers to a method that is not exposed to Objective-C
所以我必须设置处理函数:
@objc func onRegularClick(sender: UIButton)
有人可以通过引导我阅读文档来让这个菜鸟走上正确的方向,或者甚至给出一个简短的解释,在:
- 为什么我不能再简单地将函数名称字符串传递给操作?
- 遵循 Swift 方式的正确方法是什么?使用选择器 class?
- 为什么我们需要传递 @objc 关键字以及它如何影响函数?
谢谢!
- 嗯,这叫进化
当方法中有一些参数时,应该将选择器声明为:
let selector = #selector(YourClass.selector(_:))
如果选择器与调用者相同 class,您只能输入
#selector(selector(_:))
。_:
表示接受一个参数。所以,如果它接受更多的参数,你应该做这样的事情:(_:, _:)
等等。我发现
@objc
只有当函数声明为私有或对象不继承自 NSObject 时才需要
1:目前可以,但它会产生弃用警告。在 Swift 3 这将是一个错误,所以你应该尽快修复它。这个做完了 因为编译器无法检查仅使用 String if 该函数确实存在,如果它是一个有效的 Objective C 函数 可以在运行时动态解析。
2:这样做:
button.addTarget(self, action: #selector(MyViewControllerClass.buttonPressed(_:)), forControlEvents: UIControlEvents.TouchUpInside)
3: 通常你不必使用@objc 属性。我假设您的 class ViewController
(出于任何原因)不是从 UIViewController
派生的。如果它派生自 UIViewController
则还继承调用函数选择器所需的 ObjC 行为。
- why can't I no longer pass simply the function name String to the action?
不推荐使用字符串作为选择器,您现在应该写 #selector(methodName)
而不是 "methodName"
。如果 methodName() 方法不存在,您将得到一个编译错误——另一个 class 的错误在编译时被消除了。这对于字符串是不可能的。
- how is the proper way to implement this following the Swift Way? Using the Selector class?
你做对了:
button.addTarget(self, action: #selector(ClassName.methodName(_:)), forControlEvents: UIControlEvents.TouchUpInside)
- why do we need to pass the @objc keyword and how it affects the function?
在 Swift 中,通常的方法是在编译时绑定方法的调用和方法的主体(就像 C 和 C++ 那样)。 Objective C 在 运行 时间完成。所以在 Objective C 中你可以做一些在 Swift 中不可能的事情 - 例如可以在 运行 时间交换方法的实现(它被称为方法调配)。 Cocoa 旨在与 Objective C 方法一起使用,这就是为什么您必须通知编译器您的 Swift 方法应该以类似 Objective-C 的方式编译。如果您的 class 继承了 NSObject ,即使没有 @objc 关键字,它也会被编译成类似 ObjC 的风格。
对于 swift3.0 就像下面的代码一样:
yourButton.addTarget(self, action: #selector(yourButtonPressed), for: .touchUpInside)
和您的 ButtonPressed 方法
@IBAction func yourButtonPressed(sender:UIButton) {
// Do your code here
}
每个人的答案都很完美,但我有更好的方法。希望你们会喜欢。
fileprivate extension Selector {
static let buttonTapped =
#selector(ViewController.buttonTapped(_:))
}
...
button.addTarget(self, action: .buttonTapped, for: .touchUpInside)
此文件中的此处 private 将有助于仅在文件中显示 buttonTapped。
以编程方式
button.addTarget(self, action: #selector(returnAction), for: .touchUpInside)
// MARK: - Action
@objc private func returnAction(sender: UIButton) {
print(sender.tag)
}