数组修改时的执行闭包



我有以下代码:

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

如果我在数组中添加或删除项目,或者如果我这样做,这将打印"hi">

Global.notes = []

有没有办法在每次修改数组中的 Note 对象之一时打印("hi")?

感谢您的回答

在不将class更改为struct的情况下,我有两种基本方法来处理这个问题。

这是您询问的对象

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

Notes包装在作为结构的包装器中以获取结构行为。

extension Note {
struct Wrapper { let note: Note }
}
extension Global {
static var wrappedNotes = [Note.Wrapper]() {
didSet {
print("hi")
}
}
}
Global.wrappedNotes.append(Note.Wrapper(note: Note()))
Global.wrappedNotes[0] = Note.Wrapper(note: Note())
Global.wrappedNotes.remove(at: 0)

另一种方法是创建一个笔记管理器来包装对数组的访问。

class NoteManager {
subscript(index: Int) -> Note {
get {
return values[index]
}
set {
defer { onUpdate() }
values[index] = newValue
}
}
func append(_ newNote: Note) {
defer { onUpdate() }
values.append(newNote)
}
func remove(at index: Int) -> Note {
defer { onUpdate() }
return values.remove(at: index)
}
private func onUpdate() {
print("hi")
}
private var values = [Note]()
}
extension Global {
static var managedNotes = NoteManager()
}
Global.managedNotes.append(Note())
Global.managedNotes[0] = Note()
Global.managedNotes.remove(at: 0)

根据@staticVoidMan注释,如果你把你的模型,一个结构,而不是一个类,那么属性观察者didSet也将适用于你的Note模型自己的属性。

import Foundation
struct Note {
var name: String
}
struct Global {
static var notes: Array<Note> = [] {
didSet {
print("hi")            
}
}
}
Global.notes.append(Note(name: "Shubham"))
Global.notes.append(Note(name: "Bakshi"))
Global.notes[0].name = "Boxy"

这将在控制台上打印以下内容:

你好

你好

你好

SwiftArray是一个struct,而struct是值类型,这意味着当元素被添加/删除/替换时,它们会完全改变。因此,当您添加/删除/替换Note时,didSet属性观察器被调用,因为数组再次被set

但是,根据您的问题:

有没有办法在每次修改数组中的 Note 对象之一时打印("hi")?

通过这个,我假设你想在访问这个数组中的元素并修改内部属性时做一些事情。

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

<小时 />

KVO解决方案:

现在。。。由于您的Note是子类化NSObject,因此您可以使用 KVO 概念

根据下面的工作示例,我们只观察到Note类的一个属性.
如果你想观察更多的属性,那么你将需要观察更多的键路径

例:

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

笔记:

  • NSObject是 KVO 所必需的
  • @objc dynamic是使属性可观察
  • 所必需的
  • Note.message是键路径
  • noteMessageKVOs需要保持观察员的生命

最新更新