在Swift中使用选择器的正确方法

时间:2016-04-14 16:18:59

标签: ios swift selector

我以编程方式创建视图,并添加一个函数,以便操作响应UIControlEvents.TouchUpInside事件:

button.addTarget(self, action: action, forControlEvents: 
UIControlEvents.TouchUpInside)

因此,通过进入文档,我已将此操作添加为选择器:

#selector(ViewController.onRegularClick)

然后XCode抱怨:

  

#selector的参数是指未公开的方法   目标C

所以我必须设置处理函数:

@objc func onRegularClick(sender: UIButton)

有人可以通过引导我阅读文档,或者甚至简短地解释一下,将这个菜刀放在正确的方向上:

  1. 为什么我不能简单地将函数名称String传递给action?
  2. 如何按照Swift方式实现此方法?使用Selector类?
  3. 为什么我们需要传递@objc关键字及其对函数的影响?
  4. 谢谢!

6 个答案:

答案 0 :(得分:11)

  
      
  1. 为什么我不能再将函数名称String简单地传递给动作?
  2.   

不推荐使用字符串作为选择器,现在应该编写#selector(methodName)而不是"methodName"。如果methodName()方法不存在,您将收到编译错误 - 在编译时消除了另一类错误。字符串无法实现这一点。

  
      
  1. 如何按照Swift方式实现此方法?使用Selector类?
  2.   

你是以正确的方式做到的:

button.addTarget(self, action: #selector(ClassName.methodName(_:)), forControlEvents: UIControlEvents.TouchUpInside)

  
      
  1. 为什么我们需要传递@objc关键字及其对函数的影响?
  2.   

在Swift中,通常的方法是在编译时绑定方法的调用和方法的主体(比如C和C ++)。 Objective C在运行时执行此操作。所以在Objective C中你可以做一些Swift中无法实现的事情 - 例如,可以在运行时交换方法的实现(它被称为方法调配)。 Cocoa被设计为使用Objective C方法,这就是为什么你必须通知编译器你的Swift方法应该编译类似ObjectiveC的样式。如果你的类继承了NSObject,即使没有@objc关键字,它也会被编译成类似ObjC的样式。

答案 1 :(得分:7)

  1. 嗯,这叫做进化
  2. 当方法中有一些参数时,您应该将选择器声明为:

    let selector = #selector(YourClass.selector(_:))
    

    如果选择器与调用者属于同一类,则只能键入#selector(selector(_:))_:表示接受一个参数。因此,如果它接受更多参数,您应该执行以下操作:(_:, _:)等等。

  3. 我发现仅当函数声明为私有或对象不从NSObject继承时才需要@objc

答案 2 :(得分:2)

1:目前你可以,但它会创建一个已弃用的警告。在斯威夫特     3这将是一个错误,所以你应该尽快修复它。这个完成了     因为只有使用String才能被编译器检查     该函数确实存在,如果它是一个有效的Objective C函数     可以在运行时动态解析。

2:这样做:

button.addTarget(self, action: #selector(MyViewControllerClass.buttonPressed(_:)), forControlEvents: UIControlEvents.TouchUpInside)

3:通常您不必使用@objc属性。我假设您的课程ViewController(出于任何原因)不是来自UIViewController。如果它派生自UIViewController,则继承了在函数上调用选择器所需的ObjC行为。

答案 3 :(得分:1)

对于 swift3.0 ,请执行以下代码:

        yourButton.addTarget(self, action: #selector(yourButtonPressed), for: .touchUpInside)

和yourButtonPressed方法

@IBAction func yourButtonPressed(sender:UIButton) {
    // Do your code here
}

答案 4 :(得分:0)

Everyones的答案很完美,但我有一个更好的方法。希望你会喜欢。

fileprivate extension Selector {
    static let buttonTapped = 
        #selector(ViewController.buttonTapped(_:))
}
...
button.addTarget(self, action: .buttonTapped, for: .touchUpInside)

在此文件私有中,这将有助于显示仅在文件中显示buttonTapped。

答案 5 :(得分:0)

以编程方式

button.addTarget(self, action: #selector(returnAction), for: .touchUpInside)

// MARK: - Action
 @objc private func returnAction(sender: UIButton) {
        print(sender.tag)            
}