美文网首页
iOS 自动释放的NSNotificationCenter

iOS 自动释放的NSNotificationCenter

作者: 杨柳小易 | 来源:发表于2018-01-15 19:46 被阅读128次

    iOS 自动释放的NSNotificationCenter

    借鉴与 <code>fbkvocontroller</code>自己实现一个自动释放的 NSNotificationCenter,

    <code>fbkvocontroller</code> 是一个可以自动释放的kvo,并且提供了block 等方式。
    

    具体实现如下:

    @interface NSNotificationCenter(free)
    
    - (void)pbtSafe_addObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject;
    
    @end
    
    @interface PTVNotifitionToken : NSObject
    @property (nonatomic, strong) NSString* token;
    @property (nonatomic, strong) NSNotificationCenter *center;
    @property (nonatomic, weak) id observe;
    @end
    
    
    @implementation PTVNotifitionToken
    
    - (void)dealloc {
        
        if (self.center && self.token) {
            [self.center removeObserver:self.observe
                                   name:self.token
                                 object:nil];
        }
        
    }
    
    @end
    
    
    @implementation NSNotificationCenter(free)
    
    - (void)pbtSafe_addObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject {
        PTVNotifitionToken *token = [PTVNotifitionToken new];
        token.center = self;
        token.token = aName;
        token.observe = observer;
        
        objc_setAssociatedObject(observer, aName.UTF8String, token, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        [self addObserver:observer
                 selector:aSelector
                     name:aName object:anObject];
    }
    
    @end
    
    
    

    原理非常简单,调用<code> pbtSafe_addObserver </code>的时候,动态的创建一个 PTVNotifitionToken,对象,通过关联 objc_setAssociatedObject ,给 observer,

    我们知道,在自己的dealloc 函数调用之后会去释放和自己关联的obj,这样子就会调用 PTVNotifitionToken 的 dealloc 函数,然后调用 <code> removeObserver </code> 去释放。

    方案②

    static inline void BMP_EXChangeInstanceMethod(Class _originalClass ,SEL _originalSel,Class _targetClass ,SEL _targetSel){
        Method methodOriginal = class_getInstanceMethod(_originalClass, _originalSel);
        Method methodNew = class_getInstanceMethod(_targetClass, _targetSel);
        method_exchangeImplementations(methodOriginal, methodNew);
    }
    
     BMP_EXChangeInstanceMethod([NSNotificationCenter class], @selector(addObserver:selector:name:object:), [NSNotificationCenter class], @selector(BMP_addObserver:selector:name:object:));
     BMP_EXChangeInstanceMethod([UIViewController class], NSSelectorFromString(@"dealloc"), [self class], NSSelectorFromString(@"BMP_dealloc"));
    
    @implementation NSNotificationCenter (NotificationProtector)
    - (void)BMP_addObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject{
        objc_setAssociatedObject(observer, NSNotificationProtectorKey, NSNotificationProtectorValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        [self BMP_addObserver:observer selector:aSelector name:aName object:anObject];
    }
    
    @end
    
    @implementation UIViewController (NotificationProtector)
    - (void)BMP_dealloc{
        NSString *value = (NSString *)objc_getAssociatedObject(self, NSNotificationProtectorKey);
        if ([value isEqualToString:NSNotificationProtectorValue]) {
            [[NSNotificationCenter defaultCenter] removeObserver:self];
        }
        [self BMP_dealloc];
    }
    
    @end
    

    阅读博客看到的,大致原理就是hook NSNotificationCenter 的方法,然后通过关联做一个标记,等到dealloc的时候判断一下是否有添加通知这样子!

    END

    考虑使用runtime 但是系统会调用很多次 addObserver 函数,会造成重复释放这种问题。

    相关文章

      网友评论

          本文标题:iOS 自动释放的NSNotificationCenter

          本文链接:https://www.haomeiwen.com/subject/cvwdoxtx.html