Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/120.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift中的键值不显示数组中的插入和删除_Ios_Arrays_Swift_Key Value Observing - Fatal编程技术网

Ios Swift中的键值不显示数组中的插入和删除

Ios Swift中的键值不显示数组中的插入和删除,ios,arrays,swift,key-value-observing,Ios,Arrays,Swift,Key Value Observing,我创建了一个包含数组的类。我在视图控制器中向该阵列添加了一个观察者,并对该阵列进行了一些修改 问题是,当我打印observeValueForKeyPath()方法返回的更改字典时,我只能看到NSKeyValueChangeSetting类型的更改。换句话说,该方法告诉我数组已更改,为我提供了旧数组和新数组(包含所有元素),但我希望收到添加或删除了哪些特定项的信息 下面是一些示例代码 这是将观察其数组的类 private let _observedClass = ObservedClass()

我创建了一个包含数组的类。我在视图控制器中向该阵列添加了一个观察者,并对该阵列进行了一些修改

问题是,当我打印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)
    }
}

在本例中,更改字典不应该在添加到数组中时显示每个新项,使用更改类别NSKeyValueChangeInsertion?

根据Swift指南:

对于阵列,仅当执行可能修改阵列长度的操作时,才会进行复制。这包括追加、插入或删除项,或使用范围下标替换数组中的一系列项

append
操作为例。在引擎盖下,当您附加到数组时,Swift会在内存中创建一个数组,将现有
动物
数组中的项目复制到这个新数组中,再加上新项目,然后将这个新数组分配给
动物
变量。这就是为什么你只能得到
1
Setting
),因为实际上每次“编辑”都会产生一个新的数组

NSMutableArray
不同的是,它的行为更加直观—对现有阵列进行编辑(没有幕后复制到新阵列),因此,编辑后存在的数组与编辑前存在的数组相同-因此,使用键
NSKeyValueChangeKindKey
存储在
change
字典中的值可以是
.insert
remove
中的一个

然而,这还不是全部,因为您对
NSMutableArray
进行KVO兼容更改的方式取决于您使用的是Swift还是Objective-C。在Objective-C中,苹果强烈建议实施他们称之为可选的。这些只是具有标准签名的方法,可以以非常有效的方式进行符合KVO的更改

// 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];
}

当我使用
选项时,我得到了与您相同的结果:.Old |.New
。您是对的,我使用了两个选项,但只使用了一个选项发布代码。这是理想的行为,不是吗?使用此选项,新字典和旧字典都包括在内。我知道observeValueForKeyPath还应该显示添加或删除的项目,以及完整的新旧列表。对于示例的输出,我必须比较两个列表,并自己找出添加或删除了哪些元素。我在Objective中看到了一些例子,其中,当修改数组时,只显示添加和删除的元素,使用值2作为“更改种类”,它对应于NSKeyValueChangeInsertion。你能找到源吗?答案很棒。我将尝试向NSMutableArray添加一个观察者,然后看看会发生什么。谢谢我已经更新了我的答案,加入了有关如何在Swift中对
NSMutableArray
进行符合KVO的更改的信息。谢谢您的示例。在看到您的第一个答案后,我尝试使用KVO,只是将原始数组替换为NSMutableArray,但从未调用observeValueForKeyPath函数。使用mutableArrayValueForKey方法完成了这个任务。但是,您认为在Swift中检查数组中的特定更改的最佳方法是什么?回到NSMutableArray,虽然它的工作原理完全符合我的要求,但看起来像是一个黑客,因为我没有使用Swift数据结构。你仍然可以使用苹果建议的
可变索引访问器
,只需确保在对象上对
willChange:valuesAtIndexes:forKey:
/
didChange:valuesAtIndexes:forKey:
的适当调用中包装
insertObject:atIndex:
。不确定这是否比使用代理对象好,但这是一个选项。
// 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];
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    dynamic var children: NSMutableArray = NSMutableArray()


    ////////////////////////////////////

    func applicationDidFinishLaunching(aNotification: NSNotification) {

        addObserver(self,
            forKeyPath: "children",
            options: .New | .Old,
            context: &Update)

        // Get the KVO/KVC compatible array
        var childrenProxy = mutableArrayValueForKey("children")

        childrenProxy.addObject(NSNumber(integer: 20)) // .Insertion

        childrenProxy.addObject(NSNumber(integer: 30)) // .Insertion

        childrenProxy.removeObjectAtIndex(1)  // .Removal
    }
}