美文网首页
iOS NSTimer循环引用的3种解决方法

iOS NSTimer循环引用的3种解决方法

作者: 2525252472 | 来源:发表于2019-02-24 17:29 被阅读0次

    NSTimer使用时处理不好容易造成循环引用,导致控制器无法正常释放。之前使用的方法或多或少都会在某些特定环境下造成一些问题。今天正好学习到了3种解决循环引用的方法,在这里记录一下。

    1.在didMoveToParentViewController:中取消NSTimer强引用

    - (void)didMoveToParentViewController:(UIViewController *)parent{
        if (!parent) {
            [self.timer invalidate];
            self.timer = nil;
        }
    }
    

    2.利用target属性和class_addMethod,使NSTimer不直接强引用self

    @property (nonatomic , strong) id target;
    
    _target = [NSObject new];
    class_addMethod([_target class], @selector(update), (IMP)update, "v@:");
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:_target selector:@selector(update) userInfo:nil repeats:YES];
    
    void update(id self,SEL _cmd)
    {
        NSLog(@"class_addMethod ----> update");
    }
    
    - (void)dealloc
    {
        [self.timer invalidate];
        self.timer = nil;
    }
    

    3.利用NSProxy类(推荐)
    YYText中就使用到了YYTextWeakProxy作为代理中间类。有兴趣的可以去看看

    //DEProxy.h
    @interface DEProxy : NSProxy
    @property (nonatomic , weak) id target;
    @end
    
    
    //DEProxy.m
    @implementation DEProxy
    //1.1.标准转发-签名
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
    {
        return [_target methodSignatureForSelector:sel];
    }
    //1.2.标准转发-转发
    - (void)forwardInvocation:(NSInvocation *)invocation{
        [invocation invokeWithTarget:_target];
    }
    //2.快速转发
    //- (id)forwardingTargetForSelector:(SEL)selector {
    //    return _target;
    //}
    @end
    
    //使用
    @property (nonatomic , strong) DEProxy *targetProxy;
    
    _targetProxy = [DEProxy alloc];
    _targetProxy.target = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:_targetProxy selector:@selector(update) userInfo:nil repeats:YES];
    
    -(void)update{
        NSLog(@"update");
    }
    
    - (void)dealloc
    {
        [self.timer invalidate];
        self.timer = nil;
    }
    

    4.在iOS10以后,NSTimer新增了block方法来解决循环引用问题

        if (@available(iOS 10.0, *)) {
            self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
                NSLog(@"update");
            }];
        } else {
            // Fallback on earlier versions
        }
    
    - (void)dealloc
    {
        [self.timer invalidate];
        self.timer = nil;
    }
    

    相关文章

      网友评论

          本文标题:iOS NSTimer循环引用的3种解决方法

          本文链接:https://www.haomeiwen.com/subject/ajlbyqtx.html