首页 > 解决方案 > 对数组修改执行闭包

问题描述

我有以下代码:

class Note: NSObject {
}

struct Global {
    static var notes: Array<Note> = [] {
        didSet {
            print("hi")
        }
    }
}

如果我从数组中添加或删除一个项目,或者如果我这样做,这会打印“hi”

Global.notes = []

每次修改数组中的一个 Note 对象时,有没有办法打印(“hi”)?

感谢您的回答

标签: swift

解决方案


SwiftArray是 a structstructs 是值类型,这意味着当添加/删除/替换元素时它们会完全改变。因此,当您添加/删除/替换 aNote时,didSet属性观察者会set再次调用数组。

但是,根据您的问题:

每次修改数组中的一个 Note 对象时,有没有办法打印(“hi”)?

由此,我假设您想要在访问此数组中的元素并修改内部属性时执行某些操作。

如果您只处理值类型的对象,这会很好,即如果您的Note对象也是 a struct,那么更改其中的任何内容Note都会导致数组也发生更改。
但是你的Note对象是一个类,即引用类型,即使它的内部元素发生变化,它也保持同一个对象。因此,您的数组不需要更新,didSet也不会被调用。
阅读:值和引用类型


KVO 解决方案:

现在...由于您Note是子类NSObject化,您可以使用KVO 概念

根据以下工作示例,我们仅观察到Note该类的一个属性。
如果您想观察更多属性,那么您将需要观察更多的 keypaths

例子:

class Note: NSObject {
    @objc dynamic var content = ""
    
    init(_ content: String) {
        self.content = content
    }
}

class NoteList {
    var notes: [Note] = [] {
        didSet {
            print("note list updated")
            
            //register & save observers for each note
            self.noteMessageKVOs = notes.map { (note) -> NSKeyValueObservation in
                return note.observe(\Note.content, options: [.new, .old]) { (note, value) in
                    print("note updated: \(value.oldValue) changed to \(value.newValue)")
                }
            }
        }
    }
    
    //array of observers
    var noteMessageKVOs = [NSKeyValueObservation]()
}

let list = NoteList()
list.notes.append(Note("A"))   //note list updated
list.notes.append(Note("B"))   //note list updated
list.notes[0].content = "X"    //note updated: A changed to X
list.notes[1].content = "Y"    //note updated: B changed to Y

笔记:

  • NSObjectKVO 需要
  • @objc dynamic需要使属性可观察
  • \Note.message是一个关键路径
  • noteMessageKVOs需要保持观察者的生命

推荐阅读