t mutableArrayValueForKey:@transactions];
[transactions addObject:newTransaction];
2,手动通知
?
例如demo工程KVOSalaryManual
手动方式对如何和何时发送通知提供了更细粒度的控制。它可以用来减少不必要的通知,以及对多个属性发送一个通知。
通过覆盖NSObject的类方法 automaticallyNotifiesObserversForKey:实现手动通知,对需要进行手动通知的属性此方法需要返回NO,同时需要注意对于其他属性要调用父类的方法。在一个类中可以混合使用自动和手动通知。
?
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
BOOL automatic = NO;
if ([theKey isEqualToString:@openingBalance]) {
automatic = NO;
}
else {
automatic = [super automaticallyNotifiesObserversForKey:theKey];
}
return automatic;
}
手动通知的优点及要注意的地方
?
?
对于不需要发送的通知可以不再发送。也就是说在发送通知前对传入进来的参数进行测试。
?
?
if(_accountMoney !=accountMoney)
{
[self willChangeva lueForKey:@accountMoney];
_accountMoney = accountMoney;
[self didChangeva lueForKey:@accountMoney];
}
一个改变需要对应多个key。在set方法中加入多个key的改变。
?
?
[self willChangeva lueForKey:@accountMoney];
[self willChangeva lueForKey:@itemChanged];
_accountMoney = accountMoney;
_itemChanged++;
[self didChangeva lueForKey:@accountMoney];
[self didChangeva lueForKey:@itemChanged];
?
?
集合类需要注意:不仅需要提供改变的类型,还需要提供要改变的范围。
?
?
NSUInteger count = _transationsArray.count;
NSIndexSet *set = [NSIndexSetindexSetWithIndexesInRange:NSMakeRange(0, count)];
[self willChange:NSKeyValueChangeRemoval
valuesAtIndexes:set forKey:@transationsArray];
[_transationsArray removeObjectsAtIndexes:set];
[self didChange:NSKeyValueChangeRemoval valuesAtIndexes:set forKey:@transationsArray];
?
五,key之间的依赖观察。
例如demo工程KVODependentKey
例如用户有一个fullName属性,此属性被其他观察者观察。它需要依赖firstName和lastName属性。也就是说当用户设置firstName或者lastName的时候,它的fullName观察者需要得到通知。
?
这从一个方面与上面讲述的itemChanged和accountMoney有相似之处。那个里面使用了nest通知机制。通过在定制的方法中同时调用两个didChange方法。
代码如下:
?
-(void)setAccountMoneyNestChangeNotification:(int)accountMoney
{
[self willChangeva lueForKey:@accountMoney];
[self willChangeva lueForKey:@itemChanged];
_accountMoney =accountMoney;
_itemChanged++;
[self didChangeva lueForKey:@accountMoney];
[self didChangeva lueForKey:@itemChanged];
}
?
它通过封装了一层方法实现了一个属性的改变引起多个属性的修改,强调的是一改则多改。这里强调的是多个属性的修改都会影响某一个属性,多改对一改,这里采用的一种依赖机制,fullName属性依赖多个key,用户只需要告诉KVO框架是如何依赖的即可。
?
如何建立依赖关系?
?
通过keyPathsForValuesAffectingValueForKey方法返回指定key所对应的依赖set集合,框架会自动建立fullName和另外两个属性的依赖。
+(NSSet*)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keyPaths = [superkeyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@fullName]) {
NSArray *affectingKeys =@[@lastName,@firstName];
keyPaths =[keyPaths setByAddingObjectsFromArray:affectingKeys];
}
return keyPaths;
}
六,观察者模式
?
1,概念
例如demo工程ObserverDesignPattern
观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生改变的时候,所有依赖他的对象都得到通知并被自动更新。以QQ举例,你和你的qq好友时一族相互的依赖对象,当你的好友上线了,你可以看到你的好友上线的状态,当他离线了,你可以看到他的离线信息,当他更改了名字,你也可以看到他更改了名字。针对这种情况,你自身就是一个观察者,而你的好友是被观察的对象,一般称之为目标对象。你可能会问你你上线下线,你的好友也会知道呀,对的,这种情况下你自身就是一个目标对象,而你的好友就转换成了观察者了。也就是说观察者和目标对象只是在一种通知场景中的依赖关系的命名逻辑,观察者同时也可以是目标对象。下面的代码就是以这种策略思想实现的。
2,两个类
Observer观察者,或者称之为订阅者,当它观察的对象发出状态改变时候,它自己的状态改变方法会收到通知。
Subject目标:它是被观察的对象,有自己状态改变方法和的通知方法。
关于实现?
1, 基类目标对象封装了添加,删除,通知观察者的方法,派生类目标对象负责要观察的具体属性操作,并在需要通知的地方调用notifyAllObservers。
2, 基类观察者对象声明了函数update方法,它可以提供默认实现。像苹果的是observeva l