Unrecognized Selector 怎么可能出现在 Xcode9/Swift4 中?

How is UnrecognizedSelector even possible in Xcode9/Swift4?

代码完成在 #selector( 中填写方法的名称,然后在运行时继续崩溃,并出现无法识别选择器的错误,(IllegalArgumentException)。

将选择器语法重做为不再只是字符串的意义何在?

这里是选择器的创建:

headerAddButton.addTarget(section, action: #selector(addActivityToSpecificDay(sender:)), for: .touchDown)

部分(此处引用)是表视图的 header 部分(忘记提及,此代码在 Xcode 9 之前有效):

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

这里是处理程序的方法签名:

@objc func addActivityToSpecificDay (sender :UIButton)

当然在同一个源文件中。但是请阅读问题:如果代码完成可以找到它,我到底是怎么导致运行时崩溃的?

您正在像这样添加目标:

headerAddButton.addTarget(section, action: #selector(addActivityToSpecificDay(sender:)), for: .touchDown)

因为你的 #selector 没有用 class 限定 addActivityToSpecificDay,它显然与当前 class 中同名的某些方法相匹配,而不是无论 class section 是什么。

有两种选择:

  1. addActivityToSpecificDay 移动到任何 class section 中(为了说明的目的,假设它是 SectionClass)并引用 class 在你的 #selector:

    headerAddButton.addTarget(section, action: #selector(SectionClass.addActivityToSpecificDay(sender:)), for: .touchDown)
    
  2. 或者在当前class中保留addActivityToSpecificDay,但将addTarget的目标改为self

    headerAddButton.addTarget(self, action: #selector(addActivityToSpecificDay(sender:)), for: .touchDown)
    

你问:

What was the point of redoing the selector syntax as no longer just strings??

它验证了选择器的函数存在且格式正确(这是一件非常好的事情),但它显然无法验证选择器的 class 恰好与某些 class 相同其他参数(本例中的 target)。编译器无法可靠地知道 addTarget 方法如何使用选择器,也无法知道两个参数之间存在某种特殊关系。这留给了开发者。 #selector 语法有帮助,但它不是灵丹妙药。