解决 NSTimer 循环引用问题

本文探讨了NSTimer导致的循环引用问题,并提出了使用NSProxy、GCD Timer以及Block封装来避免这类问题的方法,旨在提高iOS应用的内存管理效率。

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

1、NSProxy

@implementation FirViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor orangeColor];
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:(UIBarButtonItemStylePlain) target:self action:@selector(back)];
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[[WeakProxy alloc] initWithTarget:self] selector:@selector(action:) userInfo:nil repeats:YES];
}

- (void)back
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)dealloc
{
    [self.timer invalidate];
    self.timer = nil;
    NSLog(@"=== dealloc");
}

- (void)action:(id)sender
{
    NSLog(@"====== %@",[NSDate date]);
}

@end



@implementation WeakProxy
{
    __weak id _target;
}

- (WeakProxy*)initWithTarget:(id)target
{
    _target = target;
    return self;
}

-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    return [_target methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
    if ([_target respondsToSelector:invocation.selector]) {
        [invocation invokeWithTarget:_target];
    }
    
}

@end

 

2、GCD Timer

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    /*
        参数1:_timer
        参数2:开始时间
        参数3:重复执行时间间隔
        参数4:第四个参数 leeway 指的是一个期望的容忍时间,将它设置为 1 秒,意味着系统有可能在定时器时间到达的前 1 秒或者后 1 秒才真正触发定时器。在调用时推荐设置一个合理的 leeway 值。需要注意,就算指定 leeway 值为 0,系统也无法保证完全精确的触发时间,只是会尽可能满足这个需求。
     */
    dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), 0.1*NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(_timer, ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"执行了");
        });
    });
    //开启计时器
    dispatch_resume(_timer);

 

3、Block 封装

//3、block 处理循环引用,这两个方法放在 NSTimer Category 中
+ (NSTimer *)lhScheduledTimerWithTimeInterval:(NSTimeInterval)inerval
                                      repeats:(BOOL)repeats
                                        block:(void(^)(NSTimer *timer))block {
    return [NSTimer scheduledTimerWithTimeInterval:inerval target:self selector:@selector(blcokInvoke:) userInfo:[block copy] repeats:repeats];
}

+ (void)blcokInvoke:(NSTimer *)timer {
    
    void (^block)(NSTimer *timer) = timer.userInfo;
    if (block) {
        block(timer);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值