UITextFiled的内存泄漏问题

测试设备: iPhone 6真机
系统版本: iOS 12.0.1
检测工具: 腾讯的MLeaksFinder框架

场景:

从控制器A push到控制器B, B中包含UITextFiled控件, 再由B pop回A. 此时MLeaksFinder弹出内存泄漏提示框


ml截图.png

确认问题:

调用dealloc方法, 发现控制器B确实销毁了. 但UITextFiled的dealloc方法却没有调用. 所以可以确认是UITextFiled引起的内存泄漏. 蛋疼的是, Xcode instruments检测不到该内存泄漏. 所以基本可以确定是苹果爸爸的bug了

经过查询, 发现UITextFiled引起内存泄漏的问题从iOS11.0就出现了, 于是尝试了网上的几种主流修复方式:

方案1: 创建分类, 通过私有属性textContentView拿到textField, 让textField从superView移除并设置为nil. (然并卵)

#import "UITextField+MemoryLeak.h"

@implementation UITextField (MemoryLeak)

- (void)removeFromSuperview {
    if (@available(iOS 11.0, *)) {
        id view = [self valueForKey:@"textContentView"];
        if (view) {
            [view removeFromSuperview];
            [self setValue:nil forKey:@"textContentView"];
        }
    }
}

@end

方案2: 创建分类, 通过私有属性textContentView.provider拿到textField, 将textField设置为nil. (然并卵)

#import "UITextField+MemoryLeak.h"

@implementation UITextField (MemoryLeak)

- (void)didMoveToWindow{
    [super didMoveToWindow];
    if (@available(iOS 11.2, *)) {
        NSString *keyPath = @"textContentView.provider";
        @try {
            if (self.window) {
                id provider = [self valueForKeyPath:keyPath];
                if (!provider && self) {
                    [self setValue:self forKeyPath:keyPath];
                    }
                } else {
                    [self setValue:nil forKeyPath:keyPath];
                    }
            } @catch (NSException *exception) {
                NSLog(@"%@", exception);
                }
        }
}

@end

最后不得不尝试比较苟且的方式:

方式1: 按MLeaksFinder的log提示, 在UITextFiled分类中导入NSObject+MemoryLeak头文件, 重写-willDealloc方法, 屏蔽掉弹窗

#import "UITextField+MemoryLeak.h"
#import "NSObject+MemoryLeak.h"

@implementation UITextField (MemoryLeak)

- (BOOL)willDealloc {
    return NO;
}

@end

方式2: 在 NSObject+MemoryLeak.m文件中, 将UITextFiled加入白名单. 省去创建分类的操作

+ (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"];
        }
        // 将UITextField加入白名单
        if ([systemVersion compare:@"11.0" options:NSNumericSearch] != NSOrderedAscending) {
            [whiteList addObject:@"UITextField"];
        }
    });
    return whiteList;
}

参考:
https://www.jianshu.com/p/5add8d20f8a1
https://github.com/spicyShrimp/iOS11_UITextField_Fix
https://juejin.im/post/5a56c779f265da3e243b6c34
https://github.com/Tencent/MLeaksFinder/issues/80
https://forums.developer.apple.com/thread/94323

你可能感兴趣的:(UITextFiled的内存泄漏问题)