当我向UIButton添加目标时,Swift在幕后做什么?

时间:2016-06-17 23:19:26

标签: swift uibutton

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慢得多,因为它是在它上面分层的吗?

1 个答案:

答案 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工程师非常聪明,并致力于快速高效地实现这一目标。这个效率并不是你应该担心的,特别是对于只有当用户按下按钮时才会调用的用户界面方法(即每秒数百万次)。