Key-Value Observing with NSMutableData iOS

2019-09-17 04:42发布

问题:

In my model I have NSMutableData Object called data. I want to observe it from another object and get a notification when data is added or removed.

I understand that this is a to-many relationship, so I can't use the normal KVO by first adding the observer with this code

[object addObserver:self forKeyPath:@"data" options:NSKeyValueObservingOptionNew context:NULL];

and then implement the observeValueForKeyPath:ofObject:change:context: method to do something when the notification is send.

I have read the Key-Value Observing Documentation and I found other posts about it. Observing Changes to a mutable array using KVO vs. NSNotificationCenter & Observing an NSMutableArray for insertion/removal They all use NSMutableArray as example. Is it also possible for NSMutableData? I don't understand what I have to implement then.

Can someone tell me what I exactly have to implement in which class to get KVO for a NSMutableData object working? Or if this is not possible, another solution?

Many Thanks!

回答1:

There is a common misunderstanding with KVO: It is not possible to observe the inner state of an otherwise KVO compliant property.

That's the case with the NSData: From the KVO point of view the data property of your object does not change, it's its state of the NSData that changes. If NSMutableData would expose KVO compliant properties for its contents you could observe changes by observing a key path (like @"data.contents") but that's not the case.

KVO only works for KVC compliant properties that are also documented to be KVO compliant. Most Cocoa framework classes don't give that guarantee and it's a bug to observe the objects and their key paths.

A solution for your case would be not to expose an NSMutableData as a public property but instead use an immutable data and add methods like appendData: to your custom class. That would give you the opportunity to do the changes to the data object in these methods and emit KVO notifications manually (using willChangeValueForKey:@"data" ... do the change ... didChangeValueForKey:@"data").



回答2:

KVO won't help you to observe internal changes of NSMutableData. In your example, you're observing only "data" property and you will get notification about changes only if your Model's data property is changed (e.g. you assign another instance of NSData).

In your case, I would like to propose you to use notifications: Object, which is interested in data mutations subscribes to notification of given name, and Model posts this notification every time new data was appended to Model's data.