使用计时器切换布尔值?

Posted

技术标签:

【中文标题】使用计时器切换布尔值?【英文标题】:Using an Timer to switch a Boolean value? 【发布时间】:2018-02-12 22:05:11 【问题描述】:

我对编码比较陌生,我正在尝试使用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]:无法识别的选择器发送到实例 0x604000646ed0 2018-02-13 10:55:35.664486+1300 HC 1[12286:466779] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[_SwiftValue SwitchBool]:无法识别的选择器发送到实例 0x604000646ed0” libc++abi.dylib:以 NSException 类型的未捕获异常终止 (lldb)

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

【问题讨论】:

当前视图控制器是ThirdViewController吗?顺便说一句:请遵守函数名和变量名以小写字母开头的命名约定。 你的计时器应该在某个函数内部创建,例如viewDidLoad 我建议你使用基于闭包的计时器,而不是基于选择器的。关闭可能只是display = !display; print(display) @Alexander 不过,这并不能解决 OP 遇到的问题; display 属性将无法从闭包中访问,因为 self 尚不可用。 @CharlesSrstka 我知道,这就是为什么我将此评论作为评论而不是答案提供的原因。我打算将它与答案一起考虑,而不是代替它 【参考方案1】:

如果您运行此代码,您希望输出是什么?

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

编辑:如果有问题的对象是视图控制器,则按照@vacawama 的建议,将计时器初始化为nil 并在viewDidLoad 中创建它也是一个不错的方法。基本上,您只需要确保在对象完成初始化后的某个时间点创建计时器。

【讨论】:

感谢您详细解释的答案,现在很清楚了!谢谢

以上是关于使用计时器切换布尔值?的主要内容,如果未能解决你的问题,请参考以下文章

在swift 3中保存变量和布尔值[关闭]

如果条件为真,则使用类中的布尔逻辑来设置计时器

倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何声明定时器,使用定时器TON模块 TC2

使用计时器切换图像 (SwiftUI)

IOS中切换页面如何继续计时之单例计时器

While 循环计时如何在带有多个线程的 C# 中工作?