iOS奇思妙想之使用block替代通知(二)

前言

在以前的文章iOS奇思妙想之使用block替代通知(一) )中,本身實現了通知功能。在以前的實現中,使用了Runtime進行動態綁定,雖然達到了最後的效果,可是也會增長耦合。 #解決耦合 既然動態綁定屬性會增長耦合,那麼咱們能夠考慮不讓觀察者動態綁定屬性來實現。這裏參考以前NSMapTable,將對應屬性存入,在調用的時候再根據不一樣的Key動態獲取。git

1.添加監聽

根據不一樣的觀察者和監聽類型動態生成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);
}
複製代碼

2.發送通知

根據觀察者和監聽類型動態生成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);
}
複製代碼

3.使用協議的方式來分發事件

這裏爲了使用方便,採起了Block回調的方式來監聽,可是咱們也能夠考慮協議分發的方式來實現,每一個觀察者遵照Action協議,發送通知的時候咱們就能夠找出對應觀察者,調用協議中的方法來達到事件分發的目的。async

總結

以上是對以前的代碼進行改進,但願可以給你們幫助,demo地址--->>CLActionManageride

相關文章
相關標籤/搜索