【问题标题】:Argument of '#selector' does not refer to an initializer or method'#selector' 的参数不引用初始化程序或方法
【发布时间】:2016-10-30 23:31:05
【问题描述】:

我在委托中有一个名为selectionDidFinish(controller:) 的方法来关闭委托呈现的viewController。呈现的控制器采用我的Dismissable 协议,有一个UIBarButtonItem 附加一个动作,它应该调用selectionDidFinish(controller:) 方法,但它给了我“'#selector' 的参数不'引用'初始化程序或方法”错误。

这个错误出现在UIViewController:

class FormulaInfoViewController: UIViewController, Dismissable {

    weak var dismissalDelegate: DismissalDelegate?
    override func viewDidLoad() {
        super.viewDidLoad()

    // Xcode doesn't like this selector
    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(dismissalDelegate?.selectionDidFinish(self)))
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

我已经确认dismissalDelegate 已正确设置为FormulasTableViewController,所以我不明白为什么它看不到dismissalDelegate?.selectionDidFinish(self))

我提交UIViewController的相关代码是:

class FormulasTableViewController: UITableViewController, DismissalDelegate {

  let formulas: [CalculationFormula] = [
    CalculationFormula.epley,
    CalculationFormula.baechle,
    CalculationFormula.brzychi,
    CalculationFormula.lander,
    CalculationFormula.lombardi,
    CalculationFormula.mayhewEtAl,
    CalculationFormula.oConnerEtAl]

  override func viewDidLoad() {
    super.viewDidLoad()

    let liftInfoImage = UIImage(named: "info_icon")
    let liftInfoButton = UIBarButtonItem(image: liftInfoImage, style: .Plain, target: self, action: #selector(self.segueToFormulaInfo(_:)))
    self.navigationItem.rightBarButtonItem = liftInfoButton 
  }

  func selectionDidFinish(controller: UIViewController) {
    self.dismissViewControllerAnimated(true, completion: nil)
    }

  override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let nav = segue.destinationViewController as! UINavigationController
    let vc = nav.topViewController as! Dismissable
    vc.dismissalDelegate = self
    }

  func segueToFormulaInfo(sender: UIButton) {
      performSegueWithIdentifier("segueToFormulaInfo", sender: self)
    }
}

我对如何使用#selector 进行了各种研究,我认为this post 有所有答案,但事实并非如此。

我已经尝试过这个 Dismissable 协议,无论是否将其暴露给@objc

@objc protocol Dismissable: class {
    weak var dismissalDelegate: DismissalDelegate? {
        get set }
    }

我也尝试过使用我的 DismissalDelegate 协议:

@objc protocol DismissalDelegate : class {
    func selectionDidFinish(controller: UIViewController)
}

extension DismissalDelegate where Self: UIViewController {
    func selectionDidFinish(viewController: UIViewController) {
    self.dismissViewControllerAnimated(true, completion: nil)
    }
}

我不能将我的协议扩展暴露给@objc - 这就是为什么这不起作用?我的#selector 真的是这里的问题吗?它与我的协议有关吗?

编辑:最终修复

根据接受的答案,我添加了一个函数来执行解雇:

func dismiss() {
    dismissalDelegate?.selectionDidFinish(self)
}

然后像这样调用选择器:

    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(dismiss))

【问题讨论】:

    标签: ios swift protocols selector


    【解决方案1】:

    您不能让action 参数指定任意表达式。它需要调用一个特定的选择器——该类中的一个类和函数。

    您需要在您的类中创建一个调用委托方法的函数:

    class FormulaInfoViewController: UIViewController, Dismissable {
    
        weak var dismissalDelegate: DismissalDelegate?
        override func viewDidLoad() {
            super.viewDidLoad()
    
          navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(FormulaInfoViewController.selectionDidFinish)
        }  
    
        @objc func selectionDidFinish() {
            self.dismissalDelegate?.selectionDidFinish(self)
        }
    }
    

    【讨论】:

    • ...Xcode 甚至可以使用您在“.”之前键入的名称的类的任何已知方法自动完成。它不再像 Objective-C(或 Swift 2.2),你可以传递任何字符串并让它在运行时崩溃! :-)
    猜你喜欢
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 2021-06-02
    相关资源
    最近更新 更多