2016-07-06 61 views
1

我有一个静态var类,其中存储当前的在线连接状态。我想通过其他课程观察ConnectionManager.online的价值。我想与KVO要做到这一点,但在宣布一个static变量作为dynamic导致错误:观察类中静态var的值?

class ConnectionManager: NSObject { 
    dynamic static var online = false 
    // adding 'dynamic' declaration causes error: 
    // "A declaration cannot be both 'final' and 'dynamic' 
} 

什么是这样做的最优雅的方式?

编辑:

这是我为KVO部分代码:

override func viewDidLoad() { 
    super.viewDidLoad() 

    ConnectionManager.addObserver(self, 
         forKeyPath: "online", 
         options: NSKeyValueObservingOptions(), 
         context: nil) 
} 

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 
    if keyPath == "online" { 
     print("online status changed to: \(ConnectionManager.online)") 
     // doesn't get printed on value changes 
    } 
} 

回答

3

至于现在,斯威夫特不能观察到的类属性。 (实际上,静态属性只是全局变量,其名称空间被限制在一个类中)。

如果要使用KVO,请创建一个具有online属性的共享实例(单例类),并将观察者添加到该实例。

+0

谢谢,会尝试单身模式。 – MJQZ1347

2

尝试更换dynamic static var online = false@nonobjc static var online = false

发生的事情是,因为它是从NSObject的继承,斯威夫特正试图为它生成getter和setter。因为您正在快速创建它,所以使用@nonobjc属性可以解决问题。

编辑:

我不相信你可以观察到通过志愿,因为它是如何工作

这里是一个链接静态变量和Apple's Guide on KVO

Unlike notifications that use NSNotificationCenter, there is no central object that provides change notification for all observers. Instead, notifications are sent directly to the observing objects when changes are made.

片断也许,代替使用KVO,您可以在线声明如下:

static var online = false { 
    didSet{ 
     //code to post notification through regular notification center 
    } 
} 

如果你在使用它设置,这个问题可能会点你朝着正确的方向 - 它会涉及潜水深入志愿是如何工作的:Is it possible to set up KVO notifications for static variables in objective C?

+0

谢谢,请查看更新的问题。 – MJQZ1347

+0

@ MJQZ1347最后回答 – TheBrownCoder

+0

我也想过'NSNotification',但我有点惊讶,没有其他的方法来观察静态变量。但我认为这是要走的路。另外:为什么不使用'didSet'而不是'set'? – MJQZ1347

3

我用@OOper建议的singleton模式解决了它。

class ConnectionManager: NSObject { 
    static let sharedInstance = ConnectionManager() 
    private override init() {} // This prevents others from using the default '()' initializer for this class. 
    dynamic var online = false 
} 

然后:

override func viewDidLoad() { 
    super.viewDidLoad() 
    self.tableView.tableFooterView = UIView() 

    ConnectionManager.sharedInstance.addObserver(self, 
         forKeyPath: "online", 
         options: NSKeyValueObservingOptions(), 
         context: nil) 
} 

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 
    if object is ConnectionManager && keyPath == "online" { 
     // ... 
    } 
}