我有以下代码:
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
需要保持观察员的生命