let button = UIButton()
button.addTarget(self, action: #selector(MyClass.handleButton(_:)), forControlEvents: .TouchUpInside)
@objc private func handleButton(sender: UIButton!)
{
}
我还是开始使用Swift,所以这可能是基本的,但@objc
关键字,MyClass.handleButton(_:)
中的下划线和handleButton参数后的感叹号是怎么回事?我认为旧框架在obj-c中并且Swift以某种方式链接它,但我没有得到语法。有没有更好的方法在swift中以编程方式设置按钮?在这种情况下,它不会比obj-c慢得多,因为它是在它上面分层的吗?
答案 0 :(得分:1)
@objc关键字发生了什么?
action
的{{1}}参数是addTarget
,您可以将其视为指向Objective-C函数的指针。为了获得函数的选择器,这个函数必须对Selector
可见,因为它将由Apple的框架调用,这些框架是用Objective-C编写的。有两种方法可以做到这一点:1)您的类必须是Objective-C
的子类,或者从继承自NSObject
的类继承(如NSObject
),或2)您需要将UIViewController
属性添加到Swift函数以将Swift方法暴露给Objective-C。
MyClass.handleButton(_ :)中的下划线?
下划线代表@objc
的第一个参数。在Objective-C中,第一个参数没有被命名,所以这在Swift中用handleButton
表示,这是一个通配符,意思是参数没有被命名。
_
指定一个名为MyClass.handleButton(_:)
的函数,该函数在类handleButton
中定义,带有一个参数。
如果您的MyClass
采用了两个参数,例如:
handleButton
然后选择器将@objc func handleButton(button: UIButton, forEvent event: UIEvent) {
}
显示#selector(MyClass.handleButton(_:forEvent:))
接受两个参数,第二个名为handleButton
。
指定选择器时,指定少于全名可以逃脱。你可以不用课程名称:
forEvent
并且编译器将在当前类中查找该函数。
如果你的类中只有一个#selector(handleButton(_:))
函数(它没有重载),你甚至可以不用参数规范:
handleButton
在handleButton的论证之后感叹?
#selector(handleButton)
此处,@objc private func handleButton(sender: UIButton!)
{
}
是一个隐式展开的可选,这意味着它是一个可选项,您可以使用它而无需打开它(使用UIButton!
)。这允许呼叫者传递!
而不是nil
的引用,但是当您尝试使用UIButton
时,这当然会崩溃。
这不需要是可选的。您将始终通过sender
,因此请删除不必要的UIButton
。
有没有更好的方法在Swift中以编程方式设置按钮?
不是真的,除了我已经提到的选择器的快捷方式。
在这种情况下,Swift不会比obj-c慢,因为它在它之上分层?
您正在连接Objective-C运行时。 Apple工程师非常聪明,并致力于快速高效地实现这一目标。这个效率并不是你应该担心的,特别是对于只有当用户按下按钮时才会调用的用户界面方法(即每秒数百万次)。