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;
}

参考:
//www.greatytc.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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,520评论 8 265
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,135评论 1 32
  • 年少时光里:有些事,我们轻而易举就放弃了;有些事,我们仍做着无谓的坚持。然后在一次次放弃与无谓的坚持中,感受所有晴...
    许七安是只喵阅读 190评论 0 0
  • 你以为倒霉的总是你,其实别人比你更努力
    董莺阅读 87评论 0 0
  • 家是什么? 家是儿时的记忆、 妈妈的美食 和爸爸的陪伴。 家是兄弟姐妹 和小伙伴们的嬉戏、打闹。 家是温暖、亲情、...
    若水Dewlight阅读 181评论 0 1