UIControl addTarget(_:action:for :) Swift 3.2中的方法

时间:2018-05-16 03:07:27

标签: swift addtarget

我有一个类,我们称之为ClassA,使用以下addTarget调用。

awesomeBtn.addTarget(nil, action: #selector(awesomeMethod), for: .touchUpInside)

当方法awesomeMethod在ClassA中时(即与addTarget调用相同的类),编译器接受上面的行。

但是,如果awesomeMethod不在ClassA中,让我们说它在ClassB中,那么编译器会抱怨并且我被迫在操作中指定类名。

awesomeBtn.addTarget(nil, action: #selector(ClassB.awesomeMethod), for: .touchUpInside)

在Swift的早期版本中(不完全确定哪个版本),我可以简单地编写以下内容,无论哪个类包含该方法。

awesomeBtn.addTarget(nil, action:("awesomeMethod"), forControlEvents:.touchUpInside)

想了解这是为什么或者我做错了什么,谢谢。

2 个答案:

答案 0 :(得分:1)

是的,他们从String更改了它,如果您错误地将方法名称输入到强制编译时检查方法的#selector,那么它只是一个运行时错误。他们只是想早点找到你的错误。

  

但是,如果awesomeMethod不在ClassA中,让我们说它在ClassB中,   然后编译器抱怨,我被迫指定类名   在行动中。

不,您可以指定实现该方法的@objc protocol

@objc protocol AwesomeProtocol {
    func awesomeMethod()
}

然后,即使您的类没有实现该方法,您也可以指定:

awesomeBtn.addTarget(nil, action: #selector(AwesomeProtocol.awesomeMethod), for: .touchUpInside)

注意:任何人似乎都没有必要采用该协议。该按钮搜索响应者链并使用它找到的第一个匹配方法。虽然,您应该通过任何实现awesomeMethod的类来采用该协议,以便Swift可以在编译时检测方法签名中的错误。

答案 1 :(得分:1)

基本上,Swift对你很好:)。

在旧版本中,您使用字符串文字或Selector(...)语法来编写选择器。这样做的缺点是没有编译时检查选择器是否存在。如果你在某个地方有拼写错误,你只能在运行时找到它。您不需要封闭类的名称,因为选择器只是方法的名称,不包括封闭类。在运行时,按钮自己的逻辑将在您传递的target对象中找到该选择器。没有人给出关于选择器所在类的f ** k。选择器存在于target对象中,或者不存在。

现在Swift已经改进并提供了#selector语法来编写选择器。 检查选择器是否有效。编译器需要查找具有相同名称的方法的声明。这就是为什么你必须添加类名,以便编译器知道在哪里寻找。否则它只会在当前类中查找它。但是,这并不意味着选择器将始终存在于运行时,因为在运行时,按钮会检查target是否具有该选择器,因此如果您传入另一个类的选择器(不是{的类) {1}}),按钮仍无法找到选择器。