美文网首页
MLeaksFinder 分析3:过滤不需要监测的对象

MLeaksFinder 分析3:过滤不需要监测的对象

作者: dc630f46ee2d | 来源:发表于2017-10-19 15:05 被阅读0次

前言

[strongSelf assertNotDealloc];是触发弹框的地方。调用它的方法是- (BOOL)willDealloc.

- (BOOL)willDealloc {
    NSString *className = NSStringFromClass([self class]);
    if ([[NSObject classNamesInWhiteList] containsObject:className])
        return NO;
    
    NSNumber *senderPtr = objc_getAssociatedObject([UIApplication sharedApplication], kLatestSenderKey);
    if ([senderPtr isEqualToNumber:@((uintptr_t)self)])
        return NO;
    
    __weak id weakSelf = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        __strong id strongSelf = weakSelf;
        [strongSelf assertNotDealloc];
    });
    
    return YES;
}

简单分析一下,三种情况都可以导致不触发弹框执行。

  1. [[NSObject classNamesInWhiteList] containsObject:className]为True.
  2. [senderPtr isEqualToNumber:@((uintptr_t)self)]为True.
  3. __strong id strongSelf = weakSelf;中的strongify为nil.

白名单classNamesInWhiteList

创建一个NSMutableSet对象 whiteList,不使用一个类方法,因为是一个配置列表,不需要每次重复创建,使用一个单例。在Set中的类型不监测内存泄漏

+ (NSSet *)classNamesInWhiteList {
    static NSMutableSet *whiteList;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        whiteList = [NSMutableSet setWithObjects:
                     @"UIFieldEditor", // UIAlertControllerTextField
                     @"UINavigationBar",
                     @"_UIAlertControllerActionView",
                     @"_UIVisualEffectBackdropView",
                     nil];
        
        // System's bug since iOS 10 and not fixed yet up to this ci.
        NSString *systemVersion = [UIDevice currentDevice].systemVersion;
        if ([systemVersion compare:@"10.0" options:NSNumericSearch] != NSOrderedAscending) {
            [whiteList addObject:@"UISwitch"];
        }
    });
    return whiteList;
}

根据self获取要监测的对象的类名名字。查看类的名字是否在白名单中。
如果在,退出,不会弹框。

NSString *className = NSStringFromClass([self class]);
if ([[NSObject classNamesInWhiteList] containsObject:className])
    return NO;

正在执行target-Actiontarget对象不监测内存泄漏

当用户触发执行Target-Action方法的时候,实际上在执行action方法前,是
sender对象先执行sendAction:to:forEvent方法,然后UIApplicatoin执行
sendAction:to:from:forEvent:方法,其中from就是sender对象.

这里使用方法交换截获sendAction:to:from:forEvent:,然后截获了当前sender对象保存在kLatestSenderKey

- (BOOL)swizzled_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event {
    objc_setAssociatedObject(self, kLatestSenderKey, @((uintptr_t)sender), OBJC_ASSOCIATION_RETAIN);
    
    return [self swizzled_sendAction:action to:target from:sender forEvent:event];
}

获取self的地址转换为无符号整形,如果当前检测的对象是一个正在执行action方法的sender那么,忽略不检测它的内存泄漏情况

NSNumber *senderPtr = objc_getAssociatedObject([UIApplication sharedApplication], kLatestSenderKey);
    if ([senderPtr isEqualToNumber:@((uintptr_t)self)])
        return NO;

延时后判断self是否被释放

默认情况下,UIViewController在执行pop后([objc_getAssociatedObject(self, kHasBeenPoppedKey) boolValue]为True后)的再调用Disappear接下来应该会被释放。开发者认为2秒内肯定会产生释放行为。如果被释放了,strongify就为空,不会触发弹框。

相关文章

网友评论

      本文标题:MLeaksFinder 分析3:过滤不需要监测的对象

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