ios - Key-Value Observe in Swift not showing insertions and removals in arrays -
i created class contains array. added observer array in view controller , performed modifications array.
the problem when print change dictionary returned observevalueforkeypath() method can see changes of kind nskeyvaluechangesetting. in other words, method tells me array has changed, provides me old , new arrays (containing elements) receive information of specific items added or removed.
here example code.
this class array observed.
private let _observedclass = observedclass() class observedclass: nsobject { dynamic var animals = [string]() dynamic var cars = [string]() class var sharedinstance: observedclass { return _observedclass } }
and code @ view controller.
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) } }
when run above code, result on console:
[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 )]
shouldn't, on example, change dictionary show each new item added array, using change kind nskeyvaluechangeinsertion?
according swift guide:
for arrays, copying takes place when perform action has potential modify length of array. includes appending, inserting, or removing items, or using ranged subscript replace range of items in array.
take example append
operation. under hood, when append array, swift creates new array in memory, copies items existing animals
array new array - plus new item - assigns new array animals
variable. sleight-of-hand why ever kind of 1
(setting
), because in fact each 'edit' results in new array being created.
it's different nsmutablearray
because behaviour bit more intuitive - edits are made existing array (there's no behind-the-scenes copying new array), array exists after edit same array existed before - hence value stored in change
dictionary key nskeyvaluechangekindkey
can 1 of .insertion
, .removal
, etc.
even isn't whole story however, because way make kvo compliant changes nsmutablearray
varies depending on whether you're using swift or objective-c. in objective-c, apple recommend implementing call optional mutable indexed accessors. these methods standard signature make kvo-compliant changes in efficient way.
// mutable accessors /////////////////////////////////////////// // class has property called <children> of type nsmutablearray // must have (or other insert accessor) -(void)insertobject:(nsnumber *)object inchildrenatindex:(nsuinteger)index { [self.children insertobject:object atindex:index]; } // must have (or other remove accessor) -(void)removeobjectfromchildrenatindex:(nsuinteger)index { [self.children removeobjectatindex:index]; } // optional - idea. -(void)replaceobjectinchildrenatindex:(nsuinteger)index withobject:(id)object { [self.children replaceobjectatindex:index withobject:object]; }
swift doesn't appear have these, way make kvo-compliant changes via mutable proxy object - described in nskeyvaluecoding page. here's quick example:
@nsapplicationmain class appdelegate: nsobject, nsapplicationdelegate { dynamic var children: nsmutablearray = nsmutablearray() //////////////////////////////////// func applicationdidfinishlaunching(anotification: nsnotification) { addobserver(self, forkeypath: "children", options: .new | .old, context: &update) // kvo/kvc compatible array var childrenproxy = mutablearrayvalueforkey("children") childrenproxy.addobject(nsnumber(integer: 20)) // .insertion childrenproxy.addobject(nsnumber(integer: 30)) // .insertion childrenproxy.removeobjectatindex(1) // .removal } }
Comments
Post a Comment