将参数传递给 Swift 中的 Selector [英] passing parameters to a Selector in Swift

查看:30
本文介绍了将参数传递给 Swift 中的 Selector的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个应用程序,用于跟踪大学课程的阅读作业.每个 ReadingAssignment 都包含一个 Bool 值,指示读者是否已完成阅读作业.ReadingAssignments 被收集到 WeeklyAssignment 数组中.我希望用户能够触摸标签并显示复选标记并显示作业已完成.我希望此触摸也将 .checked 属性更新为 true,以便我可以保留数据.所以,我试图让gestureRecognizer 调用labelTicked() 方法.这有效并打印到控制台.但是,当我尝试传入赋值参数时,它会编译,但在触摸时崩溃并出现无法识别的选择器"错误.我已经阅读了我可以在这里找到的每个主题,但还没有找到解决方案.他们都说:"表示带有参数的选择器,但仍然没有通过.你能看出我做错了什么吗?

I am building an app for keeping track of reading assignments for a university course. Each ReadingAssignment has included a Bool value that indicates if the reader has finished reading the assignment. The ReadingAssignments are collected into WeeklyAssignment arrays. I want to have the user be able to touch a label and have a checkmark appear and show the assignment as completed. I would like this touch to also update the .checked property to true so I can persist the data. So, I am trying to have the gestureRecognizer call the labelTicked() method. This works and prints to the console. However, when I try to pass in the assignment parameter, it compiles, but crashes on the touch with an "unrecognized selector" error. I have read every topic i can find here, and haven't found the solution. They all say ":" signifies a Selector with parameters, but still no go. Can you see what I am doing wrong?

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() 方法中更新它.感谢您的帮助.

I would also love to pass in the UILabel checkLabel so I can update it in the labelTicked() method. Thanks for your help.

推荐答案

这里有两个不同的问题:

There are two distinct problems here:

  1. 选择器的语法错误;: 不标记参数部分的开始,它只是标记该函数根本接受参数.所以点击识别器应该被初始化为 UITapGestureRecognizer(target: self, action: "labelTicked:").轻松修复.这是个好消息.

  1. The syntax for the selector is wrong; the : doesn't mark the beginning of a parameters part, it merely marks that this function takes parameters at all. So the tap recognizer should be initialized as UITapGestureRecognizer(target: self, action: "labelTicked:"). Easy fix. That is the good news.

坏消息:即使使用完美的语法,它也无法按照您在此处设置的方式工作.您的点击识别器不能将 WeeklyAssignment 对象作为参数传递.事实上,它根本无法传递任何自定义参数.至少,不是那样.

The bad news: even with perfect syntax it will not work the way you set it up here. Your tap recognizer cannot pass a WeeklyAssignment object as a parameter. In fact, it cannot pass any custom parameter at all. At least, not like that.

然而,它可以传递的是它的sender(通常是手势识别器附加到的视图).您可以通过将方法更改为

What it can pass, however, is its sender (which is usually the view the gesture recognizer is attached to). You can grab it by changing your method to

func labelTicked(sender: AnyObject) {

(请注意,AnyObject 可以声明为更具体的类型,如果您确切地知道会发生什么.)

(note that AnyObject may be declared as a more specific type if you know exactly what to expect.)

通过发送方,您现在可以从理论上推断出哪个标签已被窃听,标签对应于哪个数据实体,以及该实体的 checked 属性处于哪个状态.我认为这会很快变得非常复杂.

Going through the sender, you could now theoretically infer which label it is that has been tapped, which data entity that labels corresponds to, and which state the checked property of that entity is in. I think this would become very convoluted very quickly.

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

Seemingly straightforward things becoming convoluted is usually a good sign that we should take a step back and look for a better solution.

我建议此时放弃整个 GestureRecognizer 方法,而是利用表视图中的每个单元格已经带有自己的点击识别"功能的事实:表视图委托的 didSelectRowAtIndexPath: 方法.在那里,您可以轻松地使用提供的 NSIndexPath 从数据源检索相应的模型实体,以根据需要读取和修改其参数.通过 cellForRowAtIndexPath:,您可以获得对正确单元格的引用并相应地更改其内容.

I'd suggest dropping the whole GestureRecognizer approach at this point, and instead exploit the fact that each cell in a table view already comes with its own "tap recongizing" functionality out of the box: the didSelectRowAtIndexPath: method of the table view's delegate. There, you can easily use the supplied NSIndexPath to retrieve the corresponding model entity from the data source to read and modify its parameters as you see fit. Via cellForRowAtIndexPath: you can then get a reference to the correct cell and change its contents accordingly.

随着 Swift 语言的发展和使用基于字符串的选择器(例如 "labelTicked:")现在被标记为已弃用,我认为对答案进行小幅更新是合适的.

As the Swift language evolves and using String-based selectors (e.g. "labelTicked:") is now flagged as deprecated, I think it's appropriate to provide a small update to the answer.

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

Using more modern syntax, you could declare your function like this:

@objc func labelTicked(withSender sender: AnyObject) {

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

and initialize your gesture recognizer like this, using #selector:

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

这篇关于将参数传递给 Swift 中的 Selector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆