如何编写在Swift 3中接受参数的选择器

时间:2016-11-09 17:29:03

标签: ios swift swift3 selector

在Swift 2中,这曾经有用(我故意省略了表视图方法)......

 import Foundation
 import UIKit

 private extension Selector {
    static let didTapButton = #selector(TableVC.buttonTapped(_ :))

 }

 class TableVC: UITableViewController{

     override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
         let btnAccView:UIButton = UIButton(frame: CGRectMake(0, 0, 27, 27))
         btnAccView.addTarget(self, action: .didTapButton, forControlEvents: UIControlEvents.TouchUpInside)
         btnAccView.tag = indexPath.row
     }


     func buttonTapped(sender: UIButton){
         print("button tapped at row \(sender.tag)")
     }

 }

在Swift 3中,这会导致错误:“TableVC没有成员buttonTapped”。

我只需要编写一个带参数的选择器。 我试着用我能想到的各种方式摆弄语法,但没有任何效果。谢谢你的帮助

3 个答案:

答案 0 :(得分:3)

首先,您需要修改buttonTapped,以便抑制第一个参数标签。在内部参数标签之前插入下划线,使其如下所示:

func buttonTapped(_ sender: UIButton) {

之前,其方法签名为TableVC.buttonTapped(sender:),现在其签名为TableVC.buttonTapped(_:)。您可能必须删除扩展中下划线和冒号之间的空格,但之后应该可以使用。

作为附注,您是否有任何特殊原因在Selector使用此处的扩展程序?这种扩展模型最常用于通知名称等容易拼写错误的内容,从而导致棘手的错误。由于Swift编译器会自动验证#selector声明,无论它们放在何处,您都可以将其直接放入代码中 - 无需扩展。

答案 1 :(得分:1)

通过让编译器推断出一些函数签名,你可以省去一些悲伤。在你的情况下......

class TableVC: UIViewController {
    func buttonTapped(sender: UIButton) { /*...*/ }
}

您可以在TableVC课程外部将其引用为:

  • #selector(TableVC.buttonTapped(sender:))
  • #selector(TableVC.buttonTapped)

第二个可行,因为buttonTapped上只有一个TableVC函数,因此编译器不需要完整签名来消除歧义。

TableVC内部的代码中,您可以进一步简化它,只需使用#selector(buttonTapped),因为此时您已经进入了类范围,并且可以安全地推断出一种方法。类。

(您使用的#selector(TableVC.buttonTapped(_:))行仅在您的方法声明为func buttonTapped(_ sender: UIButton)时有效。对于您的使用案例,sender是否无关紧要参数是否有参数标签 - 您只需要在func声明和#selector表达式之间保持一致。)

正如@Bob所说,不需要Selector扩展,因为编译器已经验证了选择器。

答案 2 :(得分:0)

使用以下方式为按钮操作实现选择器:

import UIKit
class MyViewController: UIViewController {
    let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))

    override init?(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        let action = #selector(MyViewController.tappedButton)
        myButton.addTarget(self, action: action, forControlEvents: .touchUpInside)
    }

    func tappedButton(sender: UIButton?) {
        print("tapped button")
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}