Search code examples
objective-creactive-cocoa

Should I rebind models in ReactiveCocoa MVVM?


I have started setting up my view models so they automatically unbind/bind themselves to any model they represent.

I'm relatively new to ReactiveCocoa and want to know if what I'm doing is bad/good practice or if there's a better way to do it.

For example, if I have a view model that represents a movie model, I would set it up like this:

-(void)bind{
    [RACObserve(self, movieModel) subscribeNext:^(id x) {
        [self unbindMovieModel];
        [self bindMovieModel];
    }];
}

-(void)unbindMovieModel{}
-(void)bindMovieModel{
    self.titleSignal = [RACObserve(self.movieModel, title) 
        takeUntil:[self rac_signalForSelector:@selector(unbindMovieModel)];

    self.averageRatingSignal = [[self.movieModel currAverageRating] 
        takeUntil:[self rac_signalForSelector:@selector(unbindMovieModel)];

    //Setup some more complex signals, etc...
}

Now if at any point I do:

self.movieModel = newModel;

The view model will unbind from the old movieModel and bind itself to newModel.

Is there a better way? Is this not "reactive"? Any feedback would be really appreciated.


Solution

  • You can drastically simplify this case by moving the movieModel from the static to the dynamic part of the RACObserve macro:

    RAC(self.titleLabel, text) = RACObserve(self, movieModel.title);
    

    Then, your view will update both when the model instances are exchanged and when a model instance itself changes.

    If your view model contains signals itself, you can do something like the following:

    RAC(self.ratingLabel, text) = [[RACObserve(self, movieModel) map:^(id viewModel) {
        return viewModel.currAverageRating;
    }] switchToLatest];