ios - 如何在 Swift 中正确触发/调用 "selector"?

标签 ios swift timer callback selector

问题总结:

如果您有一个 Swift 类在其初始化程序中将选择器作为参数,您如何手动“触发/调用”该选择器?

完整问题:

考虑以下在 Swift 中制作自定义计时器的尝试:

let TIME_INTERVAL = 0.1

class ValueAnimator : NSObject {
    private var timer = Timer()

    private let maxRep: Int
    private var currentRepIndex: Int = 0

    private var selector: Selector

    init(durationInSeconds: Int, selector: Selector) {
        print("VALUEANIMATOR INIT")
        self.maxRep = Int(Double(durationInSeconds) / TIME_INTERVAL)
        self.selector = selector

    }

    func start() {
        timer = Timer.scheduledTimer(timeInterval: TIME_INTERVAL, target: self, selector: (#selector(timerCallback)), userInfo: nil, repeats: true)
    }

    @objc func timerCallback() {
        currentRepIndex += 1

        perform(selector) // <-------- this line causes crash, "unrecognized selector sent to instance 0x600001740030"

        print ("VA timer called!, rep: \(currentRepIndex)")
        if currentRepIndex == maxRep {
            timer.invalidate()
            print("VA timer invalidated")
        }

    }


}

这个“ValueAnimator”的用法类似于普通的 Timer/NSTimer,因为您将“选择器”作为参数传递,并且每次 ValueAnimator 触发时都会调用该选择器:

[在父类中]:

// { ...

   let valueAnimatorTest = ValueAnimator(durationInSeconds: 10, selector: #selector(self.temp))
        valueAnimatorTest.start()
    }

    @objc func temp() {
        print("temp VA callback works!") // this doesn't happen :(
    }

我正在尝试实现同样的事情,据我所知,行:

perform(selector)

应该在父类中触发选择器,但我却收到错误:“无法识别的选择器发送到实例 0x600001740030”

我有点头疼了。我尝试用谷歌搜索错误,但似乎每个人都在谈论如何从父端使用选择器(如何使用 Timer.scheduledTimer() 等),但我已经知道如何成功地做到这一点。

我也尝试过对代码进行各种调整(更改公有/私有(private)、变量范围以及 performSelector() 函数的不同形式)...但无法找到使选择器触发的正确方法...或者我犯的不相关的错误(如果有的话)。

感谢您的帮助。

最佳答案

通过调用 perform(selector) 就好像你在调用 self.perform(selector) (隐含了 self),通过这样做, ValueAnimator 类是实际执行选择器的对象。发生这种情况时,它会尝试调用 ValueAnimator 类的名为 temp() 的方法,但由于该方法不存在,应用程序正在崩溃。

您可以验证如果在 ValueAnimator 中添加 temp() 方法:

@objc func temp() {
    print("Wrong method!!!")
}

如果您现在运行,您将不会出现崩溃和“错误的选择器!!!”消息将出现在控制台上。

您的问题的解决方案是将应该运行选择器方法的对象与选择器一起传递给 ValueAnimator 对象的初始化。

在 ValueAnimator 类中声明以下属性:

private var target: AnyObject

更新 init 方法,使其可以获取目标作为参数:

init(durationInSeconds: Int, selector: Selector, target: AnyObject) {
    ...

    self.target = target
}

同时更新 timerCallback():

@objc func timerCallback() {
    ...

    _ = target.perform(selector)

    ...
}

最后,当您初始化 ValueAnimator 实例时,也传递选择器所属的对象:

let valueAnimatorTest = ValueAnimator(durationInSeconds: 10, selector: #selector(self.temp), target: self)

再次运行,这次将执行正确的 temp() 方法。

希望对你有帮助。

关于ios - 如何在 Swift 中正确触发/调用 "selector"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58945351/

相关文章:

ios - 应用程序崩溃与 NSMutableArray

c# - Jenkins 无法通过缺少对程序集 netstandard 的引用来构建 Xamarin iOS 项目

ios - 本地通知和(NSURLConnection后台下载)不起作用

swift - NSTabViewController 作为工作表顶部空间

swift - 如何在 Swift 中为 UITableView 处理数组中的两种不同类型

java - 无法在android中的服务中启动计时器

ios - 如果不先点击 Open Graph Debugger,iOS 中的 Facebook Open Graph Share 将无法正常工作

java - 我在 Timer 类中找不到 start() 方法

c - X 秒后终止程序 Linux C

arrays - 从二维数组中获取列——如何限制扩展中的数组类型?