iOS容易造成循引用的场景

场景一 :NStimer

timer就是一个能在从现在开始的未来的某一个时刻又或者周期性的执行我们指定的方法的对象
NSTimer执行的必要条件:对应线程的RunLoop要开启,mode要对应
下面看timer的循环引用:

-(void)setBlock:(TestBlock)block{
    _block = [block copy];


}
- (id)init
{

    if (self = [super init]) {
        NSLog(@" do ing!!");
        self.myTimer = [[NSTimer scheduledTimerWithTimeInterval:1
                                                    target:self
                                                  selector:@selector(handleTimer:)
                                                  userInfo:nil
                                                   repeats:YES] autorelease];

          }
    return  self;
}

- (void)handleTimer:(id)sender {
    NSLog(@"%@ say: testTimer!", [self class]);
    self.testCountView.layer.borderColor = [[UIColor whiteColor] CGColor];

}
- (void)clearTimer {


   [_myTimer invalidate];
    _myTimer = nil;
}
- (void)dealloc
{
//   [self clearTimer];
    NSLog(@"%s is dealloced",__FUNCTION__);
   [super dealloc];
}

如图,我们写这样的一个类,当我们初始化这个类就会有一个timer开启,然后当我们去释放当前类的时候,是不会走dealloc函数的,因为timer会对当前类count +1,然后timer持有self,self持有timer就造成了死循环,造成内存泄露,而打破循环引用的方法就是Invalidate。

场景 二:[self performSelector:

当方法还没有执行的时候,要返回父视图释放当前视图的时候,self的计数没有减少到0,而导致无法调用dealloc方法,出现了内存泄露
解决方案:
1.[NSObject cancelPreviousPerformRequestsWithTarget:self]
2.[NSObjectcancelPreviousPerformRequestsWithTarget:self selector:@selector(method1:)object:nil]

场景 三:addObserver

Q&A:
1.向NSNotificationCenter中addObserver后,有没有对这个对象进行引用计数加1操作?
2.在一个已经释放的NSObject类 以及一个ViewController类发通知结果会怎样?
3. [[NSNotificationCenter defaultCenter] removeObserver: name: object:nil];
和.
[[NSNotificationCenter defaultCenter] removeObserver:] 如何选取

我们首先解决第2个问题,在一个已经释放的NSObject类 以及一个ViewController类发通知 NSObject会crash,会提示一个地址错误,说明通知只是记住了他的地址指针,技术并没有加1,而对ViewController类发通知 不会发生crash,为什么会这样?
那就是:ViewController在dealloc的时候会调用 [[NSNotificationCenter defaultCenter] removeObserver:self] ;
而我们怎么去验证呢,那就是给NSNotificationCenter加一个类别,重写removeObserver:self方法,就会很容易的发现,你还会发现在dealloc的时候会移除系统的通知,实际上苹果就是这么做的。
最后一个问题:那么如何让抉择? 就是在除了Dealloc以外的地方都不要调用removeObserver:self 而是使用单个移除的方法[[NSNotificationCenter defaultCenter] removeObserver: name: object:nil];

场景四:Try 有风险,Catch需谨慎

##

 @try{
    //可能抛出异常的代码
}
@catch(NSException *exception) {
    //处理异常
}
@finally{
    //finally 代码块是可选的
    // 但如果写了 finallyblock,不管有没有异常,block 内的代码都会被执行
}

然后 我们就可以发挥了:

 @try {
        //可能抛出异常的代码

     TestTryctch*object = [[TestTryctch alloc] init];
        [object doSmMayThrowException];//异常函数
        [object release];

    }
    @catch (NSException *exception) {
        //处理异常
        NSLog(@"throw an exception:%@", exception.reason);
    }
    @finally {
        NSLog(@"finally execution");
    }

上述代码会不会有异常???
会,当然会!, [object doSmMayThrowException];//异常函数 直接就会跳过 [object release]; ,产生内存泄露

场景五:死循环

CATransition*transition = [CATransition animation];
transition.duration= 0.5;
tansition.repeatCount= HUGE_VALL;
[self.view.layeraddAnimation:transition forKey:”myAnimation”]
,如果HUGE_VALL 为一个很大的数就会内存泄露 解决方案:
-(void)viewWillDisappear:(BOOL)animated{
[self.view.layer removeAllAnimations];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值