在 class 中观察静态变量的值?
Observing a value of a static var in a class?
我有一个 class 和一个 static var
,其中存储了当前的在线连接状态。我想通过其他 classes 来观察 ConnectionManager.online
的值。我想用 KVO 来做到这一点,但是将 static
变量声明为 dynamic
会导致错误:
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
}
}
尝试将 dynamic static var online = false
替换为 @nonobjc static var online = false
发生的事情是因为它继承自 NSObject,Swift 正在尝试为其生成 getter 和 setter。因为你是在swift中创建的,所以使用@nonobjc属性解决了问题。
编辑:
我不相信你可以通过 KVO 观察静态变量,因为它的工作原理
这是来自 Apple's Guide on KVO
的 link 和片段
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
}
}
如果您打算使用它,这个问题可能会为您指明正确的方向——它将涉及更深入地研究 KVO 的工作原理:
至于现在,Swift 不能具有可观察的 class 属性。 (实际上,静态属性只是全局变量,其命名空间限制在 class 中。)
如果您想使用 KVO,请创建一个具有 online
属性 的共享实例(单例 class)并将观察者添加到该实例。
我用@OOper 建议的 singleton
模式解决了它。
class ConnectionManager: NSObject {
static let sharedInstance = ConnectionManager()
private override init() {} // This prevents others from using the default '()' initializer for this class.
@objc dynamic var online = false
}
然后:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.tableFooterView = UIView()
ConnectionManager.sharedInstance.addObserver(self,
forKeyPath: "online",
options: [.new, .initial],
context: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if object is ConnectionManager && keyPath == "online" {
// ...
}
}
我会建议 属性 包装器,我尝试了下面的示例并且非常适合我:
@propertyWrapper
struct StaticObserver<T> {
private var value:T
init(value:T) {
self.value = value
}
var wrappedValue: T {
get {
// Do your thing
return self.value
}
set {
// Do your thing before set
self.value = newValue
// Do your thing after set
}
}
@StaticObserver(value: false)
dynamic static var online:Bool
我有一个 class 和一个 static var
,其中存储了当前的在线连接状态。我想通过其他 classes 来观察 ConnectionManager.online
的值。我想用 KVO 来做到这一点,但是将 static
变量声明为 dynamic
会导致错误:
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
}
}
尝试将 dynamic static var online = false
替换为 @nonobjc static var online = false
发生的事情是因为它继承自 NSObject,Swift 正在尝试为其生成 getter 和 setter。因为你是在swift中创建的,所以使用@nonobjc属性解决了问题。
编辑:
我不相信你可以通过 KVO 观察静态变量,因为它的工作原理
这是来自 Apple's Guide on KVO
的 link 和片段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
}
}
如果您打算使用它,这个问题可能会为您指明正确的方向——它将涉及更深入地研究 KVO 的工作原理:
至于现在,Swift 不能具有可观察的 class 属性。 (实际上,静态属性只是全局变量,其命名空间限制在 class 中。)
如果您想使用 KVO,请创建一个具有 online
属性 的共享实例(单例 class)并将观察者添加到该实例。
我用@OOper 建议的 singleton
模式解决了它。
class ConnectionManager: NSObject {
static let sharedInstance = ConnectionManager()
private override init() {} // This prevents others from using the default '()' initializer for this class.
@objc dynamic var online = false
}
然后:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.tableFooterView = UIView()
ConnectionManager.sharedInstance.addObserver(self,
forKeyPath: "online",
options: [.new, .initial],
context: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if object is ConnectionManager && keyPath == "online" {
// ...
}
}
我会建议 属性 包装器,我尝试了下面的示例并且非常适合我:
@propertyWrapper
struct StaticObserver<T> {
private var value:T
init(value:T) {
self.value = value
}
var wrappedValue: T {
get {
// Do your thing
return self.value
}
set {
// Do your thing before set
self.value = newValue
// Do your thing after set
}
}
@StaticObserver(value: false)
dynamic static var online:Bool