If I have the following data model:
Model
- subModels (NSMutableArray * of type SubModel)
SubModel
- text
- createdAt
is it possible to use KVO to observe changes on the parent Model
class and still receive changes notifications for properties on relationship models?
Using ReactiveCocoa
, what I'm trying to accomplish would look something like this:
self.model = [Model new];
self.model.subModels = [NSMutableArray array];
SubModel *subModelOne = [SubModel new];
[self.model mutableArrayValueForKeyPath:@"subModels"] addObject:subModelOne];
[RACObserve(self, model) subscribeNext:^(id next){
NSLog(@"%@", next);
}];
subModelOne.text = @"Lollipop, lollipop, oh lolli lolli lolli lollipop!";
What I want to happen is I would get a next event from initializing model.subModels
to an empty array, one from adding a sub model to the relationship, and finally one from setting subModelOne.text
. Essentially I want all subproperties, submodels, etc, KVO notifications to propagate up the chain but I'm not sure how to accomplish that task.
The last paragraph in your question is the key to the solution:
So we'll have one signal watching the
subModels
property onmodel
.Not sure if you can do this specifically. With KVO, when you observe a property you're observing changes to that property, so when you observe a property that is an
NSMutableArray
object, you won't receive notifications until you change the object, by which I mean: assign a new array to that property. Adding or removing items from the array don't count as "changing the property". So the ideal way to do this would be to use an immutable array, when you need to change the items, create a newNSArray
as needed and assign it to the property. Then you can observe it. You're using themutableArrayValueForKey:
, which apparently makes thecount
property KVO-compliant. I've never used it so I'm not sure atm. Which option to go with is up to you.Our last signal will be watching the
text
property of thesubModel
.If you want a single signal that sends you events for all these changes, you use
combineLatest:reduce:
: