iOS 关于内存泄露的想法

本文介绍如何避免iOS开发中的内存泄漏问题,包括弱化self指针、正确处理NSTimer及NSNotification、利用工具检测泄漏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当实习生的时候才第一次考虑内存泄漏的问题,当时做的也很简单,无非就是几个步骤:

1.注意对self等的弱化指针的声明方法,代理使用weak,而block使用copy。 2.释放该类中的NSNotification(通知)、NSTimer(定时器)等 3.在该类的dealloc中打印,通过哪些类没有打印结果查看是出问题的类。

最近又对内存泄露有了一些新的了解,关于以上的几点有一些更好的做法:

1.self指针的弱化

关于self的弱化方式有好几种方式:

__weak __typeof(self) weakSelf = self;
__weak __typeof(&*self) weakSelf = self;
__weak UIViewController *weakSelf =self;
复制代码

很简单,一般会直接放在一个全局的文件中公用:

#define WS(ws)  __weak __typeof(&*self)ws = self;
复制代码

在block中使用实例变量时,也会引起内存泄露的警告,所以最好将要在block中使用的对象声明为属性。 如:使用下方的方法声明的bottomDetailCollectionView是一个强指针,如果在block中使用的话,会导致循环。

    lZBottomDetailCollectionView *bottomDetailCollectionView = [[lZBottomDetailCollectionView alloc] init];
    self.bottomDetailCollectionView = bottomDetailCollectionView;
    [self.view addSubview:bottomDetailCollectionView];
    WS(ws) 
    topTitleCollectionView.topTitleSelected = ^(NSInteger tag) {
      
        [ws addTopTitleUMengEvent:tag];
        NSIndexPath *indexpath = [NSIndexPath indexPathForItem:tag inSection:0];
        [bottomDetailCollectionView scrollToItemAtIndexPath:indexpath atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
    };
复制代码

应该将block中的bottomDetailCollectionView改为弱引用的ws.bottomDetailCollectionView。

2.NSTimer等的释放

刚开始学的时候,只知道NSTimer在调用方法:

[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(doSomething) userInfo:nil repeats:YES];
复制代码

会对self直接retain,导致循环调用,所以在实现NSTimer的地方必须手动加上系统相关的释放方法:

[self.timer invalidate];
 self.timer = nil;
复制代码

但是很容易忘记写这些方法,所以参考YYImage中的方法进行修改:

① 创建一个继承与NSProxy的子类
@interface lZWeekProxy : NSProxy

@property (nonatomic, weak, readonly) id target;

-(instancetype)initWithTarget:(id)target;

+(instancetype)proxyWithTarget:(id)target;

@end

@implementation lZWeekProxy
-(instancetype)initWithTarget:(id)target
{
    _target = target;
    return self;
}
+(instancetype)proxyWithTarget:(id)target
{
    return [[lZWeekProxy alloc] initWithTarget:target];
}
- (id)forwardingTargetForSelector:(SEL)selector {
    return _target;
}
@end
复制代码

对于为什么要继承于NSProxy,我的理解是: NSProxy类似于NSObject,是一个基类。其次NSProxy是一个虚类,基本上只是关于消息转发的方法,而需要的类其中一个目的就是将消息转发回target目标对象中的方法实现。

① 创建NSTimer
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[lZWeekProxy proxyWithTarget:self] selector:@selector(doSomething) userInfo:nil repeats:YES];
复制代码

在创建NSTimer时,不再对self强引用。即便没有调用系统的方法,也不会引起内存泄露的情况。

3.判断类是否出现内存泄露

一开始的时候确实傻乎乎的通过dealloc方法是否打印的方式判断,网络上确实有一些已经很使用的工具,通过追踪该对象的引用计数方式进行判断。当然任何工具都会有一定的偏差,在实际的开发中还是需要一定的判断力:

1.微信读书团队的MLeaksFinder工具

2.PLeakSniffer


在开发中难免会出现内存泄露的情况,所以一定要多加注意

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值