循环引用 --定时器

如何破除循环引用

1.避免产生循环引用

2.在适合的时机手动断环

--weak(代理) --block(block方面) --unsafe_unretained(没有增加应用计数,但是对象被回收但是指针没有置为nil)

--block破解循环引用

在MRC下--block修饰对象不会增加引用计数,避免循环引用;

在ARC下--block修饰对象会被强引用,无法避免循环引用,需手动解环。

--unsafe_unretained 不会增加引用计数,避免循环引用;如果修饰对象在某时机被释放,会产生悬垂指针,导致内存泄露

举个例子NSTimer

 

总结:通过创建一个中间对象,然后中间对象持有两个弱饮用对象,NSTImer分派的任务(fire)实际是在中间对象中实现的,在fire方法进行判断如果对象target没有被释放那就只执行selector,如果被释放就执行invalidate方法来解除runloop对timer的持有。

代码如下:


@interface NSTimer (WTimer)

+ (NSTimer *)scheduledWeakTimerInterval:(NSTimeInterval)interval
                                 target:(id)aTarget
                               selector:(SEL)aSelector
                              unserInfo:(id)userInfo
                                repeats:(BOOL)repeaters;

@end


//
//  NSTimer+WTimer.m
//  MM--NSTimer
//
//  Created by maochengfang on 2020/11/8.
//

#import "NSTimer+WTimer.h"

@interface TimerWeakObject : NSObject

@property (nonatomic, weak) id target;
@property (nonatomic, assign) SEL selector;
@property (nonatomic, weak) NSTimer *timer;

- (void)fire:(NSTimer *)timer;

@end

@implementation TimerWeakObject

- (void)fire:(NSTimer *)timer{
    if(self.target){
        if([self.target respondsToSelector:self.selector]){
            [self.target performSelector:self.selector withObject:timer.userInfo];
        }
    }else{
        [self.timer invalidate];
    }
}

@end

@implementation NSTimer (WTimer)

+ (NSTimer *)scheduledWeakTimerInterval:(NSTimeInterval)interval
                                 target:(id)aTarget
                               selector:(SEL)aSelector
                              unserInfo:(id)userInfo
                                repeats:(BOOL)repeaters{
    
    TimerWeakObject* object  = [[TimerWeakObject alloc] init];
    
    object.target = aTarget;
    object.selector = aSelector;
    object.timer = [NSTimer scheduledWeakTimerInterval:interval target:object selector:@selector(fire:) unserInfo:userInfo repeats:repeaters];
    
    return object.timer;
    
}


@end

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值