2014-07-06 20:11:26.761 k[2109:507] My love girl is fanbinbin ... Does baba know?
爸爸监管的不错,可是儿子不高兴喽。hack儿子如何能让老爸如此侵犯隐私啊?咋办呢?不自动传递变更通知不就结了!为了实现手动通知,需要重写Son的类方法+automaticallyNotifiesObserversForKey,来告知obj-c你不想自动通知观察者自己的变化,注意是类方法哦!可以通过对特定的键名返回NO来完成:
+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{
if([key isEqualToString:@"girl_friend_name"])
return NO;
return YES;
}
在Son类的实现中加入以上类方法,重新编译运行:
apple@kissAir: objc_src$./k
2014-07-06 20:37:36.726 k[2180:507] My love girl is lili ... Does baba know?
2014-07-06 20:37:36.729 k[2180:507] Yes , It's first time to induction son's girl_name!!!
2014-07-06 20:37:36.729 k[2180:507] My love girl is mimi ... Does baba know?
2014-07-06 20:37:36.730 k[2180:507] My love girl is libinbin ... Does baba know?
老爸”感应“不到喽!但是这样长了老爸会怀疑的啦,肿么宝贝儿子从不谈恋爱呢?这个不行哦!于是乎聪明的hack儿子可以再手动的通知老爸篡改后的内容啊!具体为:在Son属性写者方法的变化之前调用-willChangeva lueForKey,然后在变化之后调用-didChangeva lueForKey,重新改写写者方法吧,修改后完整代码如下:
#import#define msg(...) NSLog(__VA_ARGS__) #define mki(x) [NSNumber numberWithInt:x] @interface Son:NSObject{ NSString *girl_friend_name; } //在属性默认为atomic的情况下,如果自定义写者方法必须同时自定义读者方法, //或者将属性改为nonatomic模式。 @property(nonatomic) NSString *girl_friend_name; -(void)think; -(void)fall_in_love_with:(NSString *)girl_name; @end @implementation Son @synthesize girl_friend_name; -(void)fall_in_love_with:(NSString *)girl_name{ self.girl_friend_name = girl_name; } -(void)think{ msg(@"My love girl is %@ ... Does baba know?",girl_friend_name); } +(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{ if([key isEqualToString:@"girl_friend_name"]) return NO; return YES; } -(void)setGirl_friend_name:(NSString *)name{ [self willChangeva lueForKey:@"girl_friend_name"]; //让老爸以为自己和女学霸谈恋爱哦 girl_friend_name = @"女学霸"; [self didChangeva lueForKey:@"girl_friend_name"]; //恢复本色吧,BAD BOY... :) girl_friend_name = name; } @end @interface Baba:NSObject{ Son *son; } @property Son *son; @end @implementation Baba @synthesize son; -(id)initWithSon:(Son *)son_v{ self = [super init]; if(self){ son = son_v; [son addObserver:self forKeyPath:@"girl_friend_name" \ options:(NSKeyValueObservingOptionNew|\ NSKeyValueObservingOptionOld|NSKeyValueObservingOptionInitial) \ context:nil]; } return self; } -(void)observeva lueForKeyPath:(NSString *)key_path \ ofObject:(id)obj change:(NSDictionary *)change \ context:(void *)context{ NSString *old_name = [change objectForKey:NSKeyValueChangeOldKey]; NSString *new_name = [change objectForKey:NSKeyValueChangeNewKey]; if(!old_name){ //NSKeyValueObservingOptionInitial选项的作用,第一次hook会发一次消息 //以后每次更改会发一次消息。 msg(@"Yes , It's first time to induction son's girl_name!!!"); }else{ if([new_name isEqualToString:@"libinbin"]){ [obj fall_in_love_with:@"fanbinbin"]; } msg(@"My son's %@ change from %@ to %@ ... That's OK? :(",\ key_path,old_name,new_name); } } -(void)dealloc{ [son removeObserver:self forKeyPath:@"girl_friend_name"]; son = nil; //[super dealloc]; } @end int main(int argc