Swift - 计时器无法访问更新的实例属性

Posted

技术标签:

【中文标题】Swift - 计时器无法访问更新的实例属性【英文标题】:Swift - Timer not able to access updated instance property 【发布时间】:2020-08-19 19:32:24 【问题描述】:

我是我的 react native 项目的本地模块,我需要定期从 Objective-C 向 Swift 发送一些数据,所以我使用的是 NSNotificationCenter。我在我的 Swift 类中成功接收到数据,在附加到观察者的函数中,并将其存储在一个属性中。

如果我从任何实例方法调用访问此属性,我可以看到该值已更新。

但是,如果我在附加到 Timer 的选择器函数中访问相同的属性,它看起来好像该值尚未更新,我不知道为什么?似乎计时器选择器函数除了属性的初始值外无权访问任何东西 - 我也尝试将属性作为 userInfo 的一部分传递给 Timer,但问题是一样的。

[[NSNotificationCenter defaultCenter] postNotificationName:@"stateDidUpdate" object:nil userInfo:state];

class StateController 

  var state: Dictionary<String, Any> = Dictionary()
  var timer: Timer = Timer()
  
    func subscribeToNotifications() 
    NotificationCenter.default.addObserver(
        self, selector: #selector(receivedStateUpdate),
        name: NSNotification.Name.init(rawValue: "stateDidUpdate"), object: nil)
    

    @objc func receivedStateUpdate(notification: NSNotification) 
        if let state = notification.userInfo 
            self.state = (state as? Dictionary<String, Any>)!
            print("\(self.state)") // I can see that self.state has been updated here
        
    

    func runTimer() 
        self.timer = Timer(timeInterval: 0.1, target: self, selector: #selector(accessState(timer:)), userInfo: nil, repeats: true)
        self.timer.fire()
        RunLoop.current.add(self.timer, forMode: RunLoop.Mode.default)
        RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
    

     @objc func accessState(timer: Timer) 
        print("\(self.state)") // state is an empty Dictionary when accessed here
    

    func printState() 
        "\(self.state)" // value printed is the updated value received from the notification
    



【问题讨论】:

【参考方案1】:

我发现我创建的 Swift 类的多个实例导致了这个问题。我假设 React Native 在调用本机模块时会创建一个单例,但似乎创建了多个实例,因为我可以看到调用了多少次 init 方法。切换到单例模式为我解决了这个问题,遵循了这个出色的 video 和这个出色的 gist 关于如何在 React Native 项目中创建单例

class StateController 
    static let shared = StateController()
    private override init() 
    


【讨论】:

以上是关于Swift - 计时器无法访问更新的实例属性的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Swift 中获取 UITextField 的 .text 属性 - 错误:“实例成员 'textFieldName' 不能用于类型 'ViewController'

Xcode6-Beta3 更新后,无法使用 Swift 访问键盘信息

Xcode Playgrounds:源文件无法互相访​​问

无法直接访问 FormControl 实例。无法读取未定义的属性“无效”

无法让我在 Swift 中的计时器在 Playground 中触发

Swift 5 - 无法解释的 DateFormatter 崩溃