我有一个类,让我们称之为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)我想知道这是为什么,或者我是不是做错了什么,谢谢。
发布于 2018-05-16 03:34:48
是的,如果您将方法名称键入错误为强制对方法进行编译时检查的#selector,则会将其从#selector更改为简单的运行时错误。他们只是想早点找出你的错误。
但是,如果awesomeMethod不在ClassA中,假设它在ClassB中,那么编译器就会抱怨,我不得不在操作中指定类名。
不,您可以指定实现该方法的@objc protocol:
@objc protocol AwesomeProtocol {
func awesomeMethod()
}然后,即使您的类没有实现该方法,也可以指定:
awesomeBtn.addTarget(nil, action: #selector(AwesomeProtocol.awesomeMethod), for: .touchUpInside)注:似乎没有人有必要采用该协议。按钮搜索响应链,并使用它找到的第一个匹配方法。尽管如此,您应该通过实现awesomeMethod的任何类来采用该协议,以便Swift能够在编译时检测方法签名中的错误。
发布于 2018-05-16 06:06:26
基本上,斯威夫特对你很好:)
在旧版本中,可以使用字符串文本或Selector(...)语法来编写选择器。这样做的缺点是没有编译时检查选择器是否存在。如果您在某个地方有一个错误,您只会在运行时找到它。您不需要封装类的名称,因为选择器只是方法的名称,不包括封闭类。在运行时,按钮本身的逻辑将在您传递的target对象中找到选择器。没有人给出关于选择器在哪个类的f**k。选择器要么存在于target对象中,要么不存在。
现在Swift已经改进并提供了用于编写选择器的#selector语法。这会检查选择器是否有效。编译器需要查找具有相同名称的方法的声明。这就是为什么您必须添加类名,以便编译器知道在哪里查找。否则,它只会在当前类中查找它。但是,这并不意味着选择器在运行时总是存在的,因为在运行时,按钮检查target是否有该选择器,因此如果传入另一个类的选择器(而不是target的类),按钮仍然找不到选择器。
https://stackoverflow.com/questions/50361912
复制相似问题