使用定时器来切换布尔值?

Using an Timer to switch a Boolean value?

我对编码比较陌生,我正在尝试使用 Timer 切换布尔值。但是,我不断收到错误消息。这是我的代码:

var Display = true

var BoolTimer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(ThirdViewController.SwitchBool), userInfo: nil, repeats: true)

@objc func SwitchBool()
{
    if Display == true{
        Display = false
        print(Display)
    } else {
        Display = true
        print(Display)
    }
}

计时器用完时出现此错误:

[_SwiftValue SwitchBool]: unrecognized selector sent to instance 0x604000646ed0
2018-02-13 10:55:35.664486+1300 HC 1[12286:466779] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue SwitchBool]: unrecognized selector sent to instance 0x604000646ed0'
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

谁能帮我理解为什么会出现这个错误以及如何解决它?

如果你运行这段代码,你希望输出是什么?

import Foundation

class C: NSObject {
    var foo = type(of: self)
}

print(C().foo)

您期待看到 C,对吧?但是你得到的是:

(C) -> () -> C

原因是当您在 属性 的默认值中使用 self 时,self 指的是作为初始化过程的一部分创建的闭包,而不是对象本身。这样做的原因是 属性 默认值是在对象的 init 函数完成之前计算的,并且在对象完成初始化之前不能使用 self。因此,Objective-C 试图将 SwitchBool 方法发送到闭包,当然闭包不支持该方法。

要解决此问题,只需将 属性 lazy;这将导致 属性 在对象本身被初始化后的某个时间被初始化,这将使使用 self 成为可能并让它实际引用您的对象,正如您从以下测试中看到的那样:

import Foundation

class C: NSObject {
    lazy var foo = type(of: self)
}

print(C().foo)

输出:

C

编辑:如果所讨论的对象是视图控制器,将计时器初始化为 nil 并在 viewDidLoad 中创建它,正如@vacawama 所建议的那样,也是一个很好的方法。基本上,您只需要确保在对象完成初始化后的某个时刻创建计时器。