如何在Swift中正确fire/call一个"selector"?
How to properly fire/call a "selector" in Swift?
问题总结:
如果您有一个 Swift class 将选择器作为其初始化器中的参数,您如何手动 "fire/call" 该选择器?
完整问题:
考虑以下在 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,因为您将 "selector" 作为参数传递,并且每次触发 ValueAnimator 时都会调用该选择器:
[父 Class]:
// { ...
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)
应该触发父级 class 中的选择器,但我却收到错误:"unrecognized selector sent to instance 0x600001740030"
我有点头疼了。我曾尝试用谷歌搜索错误,但似乎每个人都在谈论如何从父端使用选择器(如何使用 Timer.scheduledTimer() 等),但我已经知道如何成功地做到这一点。
我也尝试过对代码进行各种调整(更改 public/private、变量范围和 performSelector() 函数的不同形式)...但无法找到正确的方法让选择器触发...或者我犯的无关错误(如果有的话)。
感谢您的帮助。
您在错误的对象上调用 perform:它是 NSObject
的实例方法,因此您试图在 ValueAnimator
上调用 perform
而 ValueAnimator
没有回应 "temp"
。您必须传入要执行的对象和选择器,然后使用选择器对该对象调用执行。请注意,这正是 Timer
所做的:您必须将 self 作为对象传入,并且计时器调用您在 self.
上指定的选择器
通过调用 perform(selector)
就好像你在调用 self.perform(selector)
(隐含了 self),通过这样做,ValueAnimator class 的当前实例是实际执行的对象选择器。发生这种情况时,它会尝试调用 ValueAnimator class 的一个名为 temp()
的方法,但由于它不存在,应用程序正在崩溃。
你可以验证如果你在ValueAnimator中添加一个temp()
方法:
@objc func temp() {
print("Wrong method!!!")
}
如果您 运行 现在不会崩溃,"Wrong Selector!!!" 消息将出现在控制台上。
您的问题的解决方案是将应该 运行 选择器方法的对象与选择器一起传递给 ValueAnimator 对象的初始化。
在 ValueAnimator class 中声明如下 属性:
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()
方法。
希望对您有所帮助。
问题总结:
如果您有一个 Swift class 将选择器作为其初始化器中的参数,您如何手动 "fire/call" 该选择器?
完整问题:
考虑以下在 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,因为您将 "selector" 作为参数传递,并且每次触发 ValueAnimator 时都会调用该选择器:
[父 Class]:
// { ...
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)
应该触发父级 class 中的选择器,但我却收到错误:"unrecognized selector sent to instance 0x600001740030"
我有点头疼了。我曾尝试用谷歌搜索错误,但似乎每个人都在谈论如何从父端使用选择器(如何使用 Timer.scheduledTimer() 等),但我已经知道如何成功地做到这一点。
我也尝试过对代码进行各种调整(更改 public/private、变量范围和 performSelector() 函数的不同形式)...但无法找到正确的方法让选择器触发...或者我犯的无关错误(如果有的话)。
感谢您的帮助。
您在错误的对象上调用 perform:它是 NSObject
的实例方法,因此您试图在 ValueAnimator
上调用 perform
而 ValueAnimator
没有回应 "temp"
。您必须传入要执行的对象和选择器,然后使用选择器对该对象调用执行。请注意,这正是 Timer
所做的:您必须将 self 作为对象传入,并且计时器调用您在 self.
通过调用 perform(selector)
就好像你在调用 self.perform(selector)
(隐含了 self),通过这样做,ValueAnimator class 的当前实例是实际执行的对象选择器。发生这种情况时,它会尝试调用 ValueAnimator class 的一个名为 temp()
的方法,但由于它不存在,应用程序正在崩溃。
你可以验证如果你在ValueAnimator中添加一个temp()
方法:
@objc func temp() {
print("Wrong method!!!")
}
如果您 运行 现在不会崩溃,"Wrong Selector!!!" 消息将出现在控制台上。
您的问题的解决方案是将应该 运行 选择器方法的对象与选择器一起传递给 ValueAnimator 对象的初始化。
在 ValueAnimator class 中声明如下 属性:
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()
方法。
希望对您有所帮助。