将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()方法中更新它。 谢谢你的帮助。
这里有两个不同的问题:
-
select器的语法是错误的;
:
不标记参数部分的开始,它仅表示该函数完全接受参数。 所以轻敲识别器应该被初始化为UITapGestureRecognizer(target: self, action: "labelTicked:")
。 易于修复。 这是个好消息。 -
坏消息是,即使使用完美的语法,它也不会像你在这里设置的那样工作。 您的抽头识别器无法将
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
属性设置为该行的赋值。