实现KVO的一个例子
结构:
之前写过KVO的原理,这里放一个简单的例子。
既然KVO就是一个对象监视着另一个对象,那么我就写一个这样的小故事,就是从前有一个女孩,就是OYME,她找了个男朋友OYBoyFriend,这个男朋友十分关注OYME,OYME开心,他就开心,OYME不开心他就不开心。
也就是说,OYBoyFriend的mood属性要跟着OYME的mood属性变化。
下面是每个文件的代码:
OYME.h
#import <Foundation/Foundation.h>
@interface OYME : NSObject
@property (getter=getMood,setter=setMood:)NSString *mood;
-(instancetype)initWithMood:(NSString *)myMood;
+(instancetype)meWtihMood:(NSString *)myMood;
-(void)setMood:(NSString *)mood;
-(NSString *)getMood;
+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key;
-(void)say;
@end
OYME.m
#import "OYME.h"
@implementation OYME
@synthesize mood =_mood;
-(instancetype)initWithMood:(NSString *)myMood{
self = [super init];
if(self){
[self willChangeValueForKey:_mood];
_mood=myMood;
[self didChangeValueForKey:_mood];
}
return self;
}
+(instancetype)meWtihMood:(NSString *)myMood{
return [[OYME alloc]initWithMood:myMood];
}
+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key;{
BOOL automatic=NO;
return automatic;
}
-(void)say{
NSLog(@"Girl: I'm %@!\n",_mood);
}
-(void)setMood:(NSString *)mood{
if(![_mood isEqual:mood]){
[self willChangeValueForKey:@"mood"];
_mood=mood;
[self say];
[self didChangeValueForKey:@"mood"];
}
}
-(NSString *)getMood{
return _mood;
}
@end
OYBoyFriend.h
#import <Foundation/Foundation.h>
@class OYME;
@interface OYBoyFriend : NSObject
@property NSString *mood;
-(instancetype)initWithMood:(NSString *)myMood;
+(instancetype)boyFriendWithMood:(NSString *)myMood;
-(void)sayTo:(OYME *)myGirl;
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context;
-(void)say;
@end
OYBoyFriend.m
#import "OYBoyFriend.h"
#import "OYME.h"
@implementation OYBoyFriend
-(instancetype)initWithMood:(NSString *)myMood{
self=[super init];
if(self){
_mood=myMood;
}
return self;
}
+(instancetype)boyFriendWithMood:(NSString *)myMood{
return [[OYBoyFriend alloc]initWithMood:myMood];
}
-(void)sayTo:(OYME *)myGirl{
NSLog(@"Boy: You're %@, I'm %@",myGirl.mood,_mood);
}
-(void)say{
NSLog(@"Boy: I'm %@!\n",_mood);
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
if ([keyPath isEqual:@"mood"]) {
_mood=[[change objectForKey:NSKeyValueChangeNewKey] copy];
[self say];
}
}
@end
写完这个故事的main.m
#import <Foundation/Foundation.h>
#import "OYStudent.h"
#import "OYME.h"
#import "OYBoyFriend.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
OYBoyFriend *boyFriend=[OYBoyFriend boyFriendWithMood:@"soso"];
[boyFriend say];
OYME *me=[OYME meWtihMood:@"sad"];
[me addObserver:boyFriend forKeyPath:@"mood" options:NSKeyValueObservingOptionNew context:NULL];
[me setMood:@"happy"];//me的setMood方法里调用了me的say方法。如果不在这个set方法中调用,而是在setMood之后紧接着调用say方法的话,效果和现在的不一样。
[boyFriend sayTo:me];
[me removeObserver:boyFriend forKeyPath:@"mood"];
}
return 0;
}
运行结果就是这个样子:
这样的男朋友你想要吗????