将parameter passing给Swift中的Selector

我正在构build一个跟踪大学课程阅读作业的应用程序。 每个ReadingAssignment都包含一个Bool值,用于指示阅读者是否完成阅读任务。 ReadingAssignments被收集到WeeklyAssignment数组中。 我希望让用户能够触摸标签,并出现复选标记,并将分配显示为已完成。 我想这个接触也更新.checked属性为true,所以我可以坚持数据。 所以,我试图让gestureRecognizer调用labelTicked()方法。 这工作和打印到控制台。 但是,当我尝试传递赋值参数时,它会编译,但碰到“无法识别的select器”错误。 我已经阅读了我可以在这里find的每一个主题,并且没有find解决scheme。 他们都说“:”表示带有参数的select器,但还是没有。 你能看到我做错了吗?

func configureCheckmark(cell: UITableViewCell, withWeeklyAssignment assignment: WeeklyAssignment) { let checkLabel = cell.viewWithTag(1002) as! UILabel checkLabel.userInteractionEnabled = true let gestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("labelTicked:assignment")) checkLabel.addGestureRecognizer(gestureRecognizer) } @objc func labelTicked(assignment: WeeklyAssignment) { assignment.toggleCheckmark() if assignment.checked { label.text = "✔︎" } else { label.text = "" } } 

我也喜欢传入UILabel checkLabel,所以我可以在labelTicked()方法中更新它。 谢谢你的帮助。

这里有两个不同的问题:

  1. select器的语法是错误的; :不标记参数部分的开始,它仅表示该函数完全接受参数。 所以轻敲识别器应该被初始化为UITapGestureRecognizer(target: self, action: "labelTicked:") 。 易于修复。 这是个好消息。

  2. 坏消息是,即使使用完美的语法,它也不会像你在这里设置的那样工作。 您的抽头识别器无法将WeeklyAssignment对象作为parameter passing。 实际上,它根本无法传递任何自定义参数。 至less,不是那样的。

它可以传递的是它的sender (通常是手势识别器连接的视图)。 你可以通过改变你的方法来抓住它

 func labelTicked(sender: AnyObject) { 

(请注意,如果您确切知道期望什么, AnyObject可以将AnyObject声明为更具体的types。)

通过发送者,你现在可以从理论上推断出哪个标签被点击了,标签对应哪个数据实体,哪个状态是该实体的被checked属性。我想这很快会变得非常复杂。

看似简单的事情变得复杂化通常是一个好兆头,我们应该退后一步,寻找更好的解决scheme。

我build议在这个时候删除整个GestureRecognizer方法,而是利用这样一个事实,即表视图中的每个单元格都已经具有自己的“tap recongizing”functiondidSelectRowAtIndexPath:表视图委托的didSelectRowAtIndexPath:方法。 在那里,你可以很容易地使用提供的NSIndexPath从数据源中检索相应的模型实体,以便根据需要读取和修改其参数。 通过cellForRowAtIndexPath:你可以得到一个正确的单元格的引用并相应地改变其内容。


Swift 3的更新:

随着Swift语言的发展,使用基于string的select器(例如"labelTicked:" )现在被标记为不推荐使用,我认为适当的做法是提供一个小的更新。

使用更现代的语法,你可以像这样声明你的函数:

 @objc func labelTicked(withSender sender: AnyObject) { 

并像这样初始化你的手势识别器,使用#selector

 UITapGestureRecognizer(target: self, action: #selector(labelTicked(withSender:))) 

该function的正确select器是labelTicked: 此外,您可以直接使用string作为select器。 从而:

 let gestureRecognizer = UITapGestureRecognizer(target: self, action: "labelTicked:") 

但是当识别器触发时,您无法安排将任意对象传递给方法。 更好的方法是创buildUITableViewCell的子类。 我们称之为AssignmentCell 。 为该子类assignment一个assignment属性,并将labelTicked:方法移动到AssignmentCell

如果在故事板中devise了单元格,则可以在故事板右侧的标签中添加一个水龙头识别器,然后将识别器连接到故事板中单元格的labelTicked:方法。

在您的表视图数据源的tableView(_:cellForRowAtIndexPath:) ,在您将单元出列后,将其assignment属性设置为该行的赋值。