我试图通过用一个switch语句替换典型的长嵌套if / else语句来提高我的KVO observeValueForKeyPath实现的可读性。
到目前为止,唯一真正有用的是:
private let application = UIApplication.sharedApplication()
switch (object!, keyPath!) {
case let (object, "delegate") where object as? UIApplication === application:
appDelegate = application.delegate
break
...
default:
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
如果有的话,更难以阅读:
if object as? UIApplication === application && keyPath! == "delegate" {
}
else {
}
是否有人在observeValueForKeyPath
(及类似方法)
编辑:与下面的@ critik问题相关,这里有更多的代码来演示使用switch (object as! NSObject, keyPath!) {
时出现的问题:
private let application = UIApplication.sharedApplication()
private var appDelegate : UIApplicationDelegate?
private var rootWindow : UIWindow?
public override func observeValueForKeyPath(
keyPath: String?,
ofObject object: AnyObject?,
change: [String : AnyObject]?,
context: UnsafeMutablePointer<Void>) {
switch (object as! NSObject, keyPath!) {
case (application, "delegate"):
appDelegate = application.delegate
(appDelegate as? NSObject)?.addObserver(self, forKeyPath: "window", options: [.Initial], context: nil)
break
case (appDelegate, "window"):
rootWindow = appDelegate?.window?.flatMap { $0 }
break
case (rootWindow, "rootViewController"):
rebuildViewControllerList(rootWindow?.rootViewController)
break
default:
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
}
答案 0 :(得分:0)
元组上的switch
怎么样:
switch (object as! NSObject, keyPath!) {
case (application, "delegate"):
appDelegate = application.delegate
...
default:
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
注意事项1。虽然我再次被迫使用Swift(向下倾斜,解包等),但你可以安全地强制转发NSObject
而不会发生崩溃,因为{{{ 3}},KVO仅适用于NSObject
子类。
注2。你在Swift中也不需要break
,这也会使你的代码缩短至少一行:)
答案 1 :(得分:0)
这并没有真正解决在switch
中使用observeValueForKey
的问题,但它确实演示了如何简化问题空间以消除冗长的代码。
我创建了一个实用程序类KVOValueWatcher
,它允许我在对象的单个属性上添加(和删除)KVO观察:
public class KVOValueWatcher<ObjectType:NSObject, ValueType:NSObject> : NSObject {
public typealias OnValueChanged = (ValueType?, [String:AnyObject]?) -> ()
let object : ObjectType
let keyPath : String
let options : NSKeyValueObservingOptions
let onValueChanged : OnValueChanged
var engaged = false
public init(object:ObjectType, keyPath:String, options : NSKeyValueObservingOptions = [], onValueChanged: OnValueChanged) {
self.object = object
self.keyPath = keyPath
self.onValueChanged = onValueChanged
self.options = options
super.init()
engage()
}
deinit {
if(engaged) {
print("KVOValueWatcher deleted without being disengaged")
print(" object: \(object)")
print(" keyPath: \(keyPath)")
}
disengage()
}
public func engage() {
if !engaged {
self.object.addObserver(self, forKeyPath: keyPath, options: options, context: nil)
engaged = true
}
}
public func disengage() {
if engaged {
self.object.removeObserver(self, forKeyPath: keyPath)
engaged = false
}
}
override public func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
self.onValueChanged(((object as? NSObject)?.valueForKeyPath(keyPath!) as? ValueType), change)
}
}
我的问题代码变为:
rootWindowWatcher = KVOValueWatcher(object: applicationDelegate as! NSObject, keyPath: "window", options: [.Initial]) { window, changes in
self.rootViewWatcher?.disengage()
self.rootViewWatcher = nil
if let window = window {
self.rootViewWatcher = KVOValueWatcher(object: window, keyPath: "rootViewController", options: [.Initial]) {
[unowned self] rootViewController, changes in
self.rootViewController = rootViewController
self.rebuildActiveChildWatchers()
}
}
}
改变的主要原因是因为保持所有不同的观察并正确地添加和删除它们正成为一场噩梦。添加包装类可以消除问题和组观察属性以及属性在同一位置更改时要采取的操作。