How to get View object to respond to changes to its data source

61 views Asked by At

Say I have a CatModel object:

@interface CatModel : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) UIImage *catImage;

- (void)addWhisker:(Whisker*)whisker;

And I have a CatView:

@interface CatView : UIView

@property (nonatomic, strong) CatModel *dataSource;

@end

I want the CatView to automatically add a whisker image when it detects that a whisker was added to its dataSource. I don't want to add a Whisker to the CatModel instance and also add an addWhisker method to the CatView. What's the best way to do this?

1

There are 1 answers

0
akashivskyy On BEST ANSWER

Sounds like you may use key-value observing, but unfortunately, NSArray or any other collections are not KVO-compatible.

Instead, you may wish to create a delegate functionality:

@protocol CatModelObserving

@optional

- (void)catModel:(CatModel *)model didAddWhisker:(Whisker *)whisker;

@end

...  

@interface CatModel


@property (weak, nonatomic) id <CatModelObserving> observer;

@end

Then you would ensure that the CatView conforms to that protocol and implements that method:

- (void)catModel:(CatModel *)model didAddWhisker:(Whisker *)whisker {
    // handle it properly
}

In your CatModel.m, inside the -addWhisker: method you should notify the observer that a whisker has been added:

if (self.observer && [self.observer respondsToSelector:@selector(catModel:didAddWhisker:)]) {
    [self.observer catModel:self didAddWhisker:whisker];
}

If you wish to have multiple "observers", you may consider using GCD and block-based "notifications", like so:

[catModel addDidAddWhiskerBlock:^(Whisker *whisker) {
    // handle it properly
}];

But I will not discuss that method in this answer. As a hint I can suggest using NSMutableArray storing all those blocks, then iteratiating through those blocks in the -addWhisker: method and calling each block.