在以前的文章iOS奇思妙想之使用block替代通知(一) )中,本身實現了通知功能。在以前的實現中,使用了Runtime
進行動態綁定,雖然達到了最後的效果,可是也會增長耦合。 #解決耦合 既然動態綁定屬性會增長耦合,那麼咱們能夠考慮不讓觀察者動態綁定屬性來實現。這裏參考以前NSMapTable
,將對應屬性存入,在調用的時候再根據不一樣的Key動態獲取。git
根據不一樣的觀察者和監聽類型動態生成Key,使用NSMapTable
將對應Key和觀察者設置的屬性儲存。github
+ (void)addObserver:(id)observer type:(CLActionType)type mainThread:(BOOL)mainThread actionBlock:(void(^)(id observer, NSDictionary *dictionary))actionBlock {
dispatch_semaphore_wait([CLActionManager sharedManager].semaphore, DISPATCH_TIME_FOREVER);
NSString *key = [NSString stringWithFormat:@"%@-%@",[NSString stringWithFormat:@"%p",observer], [[self keyWithActionType:type] stringByAppendingString:@"-1"]];
NSString *actionBlockKey = [key stringByAppendingString:@"-CLActionBlock-1"];
NSString *actionMainThreadKey = [key stringByAppendingString:@"-CLActionMainThread-1"];
NSMutableDictionary *blockDictionary = [[CLActionManager sharedManager].blockDictionaryMapTable objectForKey:observer];
if (!blockDictionary) {
blockDictionary = [NSMutableDictionary dictionary];
}
[blockDictionary setObject:actionBlock forKey:actionBlockKey];
NSMutableDictionary *mainThreadDictionary = [[CLActionManager sharedManager].mainThreadDictionaryMapTable objectForKey:observer];
if (!mainThreadDictionary) {
mainThreadDictionary = [NSMutableDictionary dictionary];
}
[mainThreadDictionary setObject:[NSNumber numberWithBool:mainThread] forKey:actionMainThreadKey];
[[CLActionManager sharedManager].observerMapTable setObject:observer forKey:key];
[[CLActionManager sharedManager].blockDictionaryMapTable setObject:blockDictionary forKey:observer];
[[CLActionManager sharedManager].mainThreadDictionaryMapTable setObject:mainThreadDictionary forKey:observer];
dispatch_semaphore_signal([CLActionManager sharedManager].semaphore);
}
複製代碼
根據觀察者和監聽類型動態生成Key,而後找出對應觀察者的屬性,而後一一調用。bash
+ (void)postType:(CLActionType)type dictionary:(NSDictionary *)dictionary {
dispatch_semaphore_wait([CLActionManager sharedManager].semaphore, DISPATCH_TIME_FOREVER);
NSArray<NSString *> *keyArray = [[[CLActionManager sharedManager].observerMapTable keyEnumerator] allObjects];
NSString *identifier = [[self keyWithActionType:type] stringByAppendingString:@"-1"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF ENDSWITH %@",identifier];
NSArray<NSString *> *array = [keyArray filteredArrayUsingPredicate:predicate];
for (NSString *key in array) {
NSString *actionBlockKey = [key stringByAppendingString:@"-CLActionBlock-1"];
NSString *actionMainThreadKey = [key stringByAppendingString:@"-CLActionMainThread-1"];
id observer = [[CLActionManager sharedManager].observerMapTable objectForKey:key];
NSMutableDictionary *blockDictionary = [[CLActionManager sharedManager].blockDictionaryMapTable objectForKey:observer];
NSMutableDictionary *mainThreadDictionary = [[CLActionManager sharedManager].mainThreadDictionaryMapTable objectForKey:observer];
void(^block)(id observer, NSDictionary *dictionary) = [blockDictionary objectForKey:actionBlockKey];
BOOL mainThread = [[mainThreadDictionary objectForKey:actionMainThreadKey] boolValue];
if (block) {
if (mainThread) {
dispatch_async(dispatch_get_main_queue(), ^{
block(observer, dictionary);
});
}else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
block(observer, dictionary);
});
}
}
}
dispatch_semaphore_signal([CLActionManager sharedManager].semaphore);
}
複製代碼
這裏爲了使用方便,採起了Block回調的方式來監聽,可是咱們也能夠考慮協議分發的方式來實現,每一個觀察者遵照Action協議,發送通知的時候咱們就能夠找出對應觀察者,調用協議中的方法來達到事件分發的目的。async
以上是對以前的代碼進行改進,但願可以給你們幫助,demo地址--->>CLActionManageride