1. 主页 > 小妙招

Swift与Objective-C对象初始化对比:避免内存泄漏的5个技巧


??开头:??
刚学iOS开发的小白有没有这种经历?明明跟着教程写代码,程序跑着跑着就卡死闪退,手机烫得像暖手宝…这时候老司机一句“你内存泄漏了吧”直接让你懵圈。??Swift和Objective-C初始化对象到底有什么坑?为什么改了几行代码就能从“疯狂崩溃”到“丝滑运行”???

(顺便插一嘴,新手如何快速涨粉?和写代码一样——少踩坑多偷师!)


一、先搞懂这两个祖宗的区别

??Objective-C的初始化像开手动挡车:??
你得自己挂挡踩离合,比如用alloc init分配内存:

objective复制
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];  

这里alloc申请内存,initWithFrame装修对象,??万一忘了调用super init,内存直接乱套??。

??Swift的初始化像自动驾驶:??
直接let view = UIView(frame: .zero)完事,但别高兴太早!??如果class里属性没初始化完就敢用self,编译器当场给你报错??。

??关键区别表格:??

??对比项????Objective-C????Swift??
??初始化语法??显式调用alloc init自动内存管理,直接构造函数
??必填项检查??不检查是否初始化所有属性强制要求所有属性有初始值
??内存管理??手动retain/release(ARC前)自动引用计数(ARC)

二、内存泄漏的5个经典翻车现场

??技巧1:?? 别让对象互相“死锁”

??场景:?? 两个类A和B,A强引用B,B也强引用A。

  • ??Objective-C解法:??
    objective复制
    @interface ClassA : NSObject  
    @property (nonatomic, weak) ClassB *b;  // 用weak打断循环链  
    @end  
  • ??Swift解法:??
    swift复制
    class ClassA {  
        weak var b: ClassB?  // 加weak标记  
    }  

??说白了,就像情侣吵架——总得有一方先服软(weak),不然关系迟早崩盘。??

??技巧2:?? 闭包不是你想用就能用

??Swift里闭包偷偷强引用self最常见??:

swift复制
networkRequest { [weak self] in  // 漏了weak就完犊子  
    self?.updateUI()  
}  

??Objective-C的block也得小心:??

objective复制
__weak typeof(self) weakSelf = self;  
[self doTask:^{  
    [weakSelf reloadData];  // 必须用weakSelf  
}];  

??技巧3:?? 通知中心是个“渣男”

??用完不注销监听?内存泄漏分分钟找上门??:

  • ??Objective-C??要在dealloc里写:
    objective复制
    [[NSNotificationCenter defaultCenter] removeObserver:self];  
  • ??Swift??更推荐用deinit
    swift复制
    deinit {  
        NotificationCenter.default.removeObserver(self)  
    }  

??技巧4:?? 定时器比前任还难甩掉

??Objective-C的NSTimer必须手动invalidate??:

objective复制
[_timer invalidate];  // 忘写这句?对象永远无法释放  
_timer = nil;  

??Swift的Timer可以用weak自动解绑??:

swift复制
weak var weakTimer: Timer?  
weakTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in }  

??技巧5:?? 别把ViewController当垃圾桶

??在ViewController里疯狂addSubview却不remove???

swift复制
// 错误示范:  
view.addSubview(childVC.view)  // 没走addChild流程  
// 正确姿势:  
addChild(childVC)  
view.addSubview(childVC.view)  
childVC.didMove(toParent: self)  

??Objective-C同理,乱加子视图会导致控制器无法释放。??


三、自问自答:小白最想问的

??Q:为什么Swift比Objective-C更容易避免泄漏???
A:因为??Swift编译器会逼着你填坑??!比如属性没初始化不让编译,而Objective-C只会运行时崩溃,坑死新手不偿命。

??Q:用ARC就万事大吉了吗???
A:想得美!ARC只能解决??引用计数问题??,遇到循环引用、CoreFoundation对象(比如CGImageRef)还是得手动处理。

??Q:怎么快速检测内存泄漏???
A:Xcode自带的??Memory Graph Debugger??(那个三层图标)点一下,红色箭头指哪哪有鬼!


小编观点

小编觉得,??内存泄漏就像牙疼——平时不注意,发作起来要人命??。Swift虽然比Objective-C安全,但也不是免死金牌。多写多踩坑,再用Instruments工具定期“体检”,才能从“内存刺客”进化成“代码老中医”。

最后送一句暴论:??凡是不写weak的闭包,都是耍流氓!??

(完)

本文由嘻道妙招独家原创,未经允许,严禁转载