我创建了一个包含数组的类。我在视图控制器中向该数组添加了一个观察者,并对该数组执行了一些修改。
问题是当我打印observeValueForKeyPath()方法返回的更改字典时,我只能看到类型NSKeyValueChangeSetting的更改。换句话说,该方法告诉我数组已更改,向我提供旧的和新的数组(包含所有元素),但我希望收到添加或删除特定项的信息。
以下是一些示例代码。
这是将观察其数组的类。
private let _observedClass = ObservedClass()
class ObservedClass: NSObject {
dynamic var animals = [String]()
dynamic var cars = [String]()
class var sharedInstance: ObservedClass {
return _observedClass
}
}
这是我的视图控制器的代码。
class ViewController: UIViewController {
var observedClass = ObservedClass.sharedInstance
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
observedClass.addObserver(self, forKeyPath: "animals", options: .New | .Old, context: nil)
}
deinit {
observedClass.removeObserver(self, forKeyPath: "animals")
}
override func viewDidLoad() {
super.viewDidLoad()
observedClass.animals.insert("monkey", atIndex: 0)
observedClass.animals.append("tiger")
observedClass.animals.append("lion")
observedClass.animals.removeAtIndex(0)
}
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
println(change)
}
}
当我运行上面的代码时,我在控制台上得到了这个结果:
[kind: 1, old: (
), new: (
monkey
)]
[kind: 1, old: (
monkey
), new: (
monkey,
tiger
)]
[kind: 1, old: (
monkey,
tiger
), new: (
monkey,
tiger,
lion
)]
[kind: 1, old: (
monkey,
tiger,
lion
), new: (
tiger,
lion
)]
不应该,在这个例子中,更改字典使用更改类型NSKeyValueChangeInsertion来显示添加到数组中的每个新项目吗?
答案 0 :(得分:12)
根据Swift指南:
对于数组,只有在执行可能会修改数组长度的操作时才会进行复制。这包括追加,插入或删除项目,或使用范围下标来替换数组中的一系列项目。
以append
操作为例。在引擎盖下,当你附加到你的数组时,Swift会在内存中创建一个 new 数组,将现有animals
数组中的项目复制到这个新数组中 - 加上新项目 - 然后分配这个新数组到animals
变量。这就是为什么你只得到1
(Setting
)的原因,因为实际上每个' edit '实际上都会导致创建一个新的数组
它与NSMutableArray
不同,因为行为更直观 - 编辑 对现有数组进行编辑(没有幕后复制到新数组),所以编辑后存在的数组与之前存在的数组相同 - 因此存储在change
字典中且密钥为NSKeyValueChangeKindKey
的值可以是.Insertion
之一,{{1}等等。
然而,即使这不是整个故事,因为根据您使用的是Swift还是Objective-C,将KVO兼容更改为.Removal
的方式会有所不同。在Objective-C中,Apple强烈建议实现他们所谓的可选mutable indexed accessors。这些只是具有标准签名的方法,可以非常有效地进行符合KVO的更改。
NSMutableArray
Swift似乎没有这些,因此进行KVO兼容更改的唯一方法是通过NSKeyValueCoding页面中描述的可变代理对象。这是一个非常简单的例子:
// Mutable Accessors ///////////////////////////////////////////
// This class has a property called <children> of type NSMutableArray
// MUST have this (or other insert accessor)
-(void)insertObject:(NSNumber *)object inChildrenAtIndex:(NSUInteger)index {
[self.children insertObject:object atIndex:index];
}
// MUST have this (or other remove accessor)
-(void)removeObjectFromChildrenAtIndex:(NSUInteger)index {
[self.children removeObjectAtIndex:index];
}
// OPTIONAL - but a good idea.
-(void)replaceObjectInChildrenAtIndex:(NSUInteger)index withObject:(id)object {
[self.children replaceObjectAtIndex:index withObject:object];
}