美文网首页
NSTimer 的相关问题

NSTimer 的相关问题

作者: 刺骨寒 | 来源:发表于2019-10-01 19:54 被阅读0次

    NSTimer 循环引用问题

    使用此方法创建,会形成循环引用,即使在dealloc中调用
    [self.timer invalidate]以及self.timer = nil;也是解决不了循环引用的问题。

    产生循环引用原因:当前VC 持有timer,但是timer有对传入的target有强引用,以此形成循环引用。

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTest) userInfo:nil repeats:YES];
    

    解决方法:
    1.通过中间件来进行解除循环引用,使用代理对象来进行强引用timer, vc对其代理对象弱引用,以此来解决。
    创建一个代理对象LProxy,

    LProxy.h
    @interface LProxy : NSObject
    
    +(instancetype)proxyWithTarget:(id)target;
    @property (nonatomic, weak) id target;
    
    @end
    
    LProxy.m
    #import <objc/runtime.h>
    @implementation LProxy
    +(instancetype)proxyWithTarget:(id)target{
        LProxy *p = [[LProxy alloc]init];
        p.target = target;
        return p;
    }
    //此处是为了在使用时target为当前的LProxy,但是找不到LProxy的timerTest方法出现carch,通过消息转发来实现消息的接受者为传入的target来,以此解决因找不到target的方法出现的carch
    - (id)forwardingTargetForSelector:(SEL)aSelector{
        return self.target;
    }
    @end
    
    在使用的时候,通过代理对象的target来进行一步弱引用解决循环
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[LProxy proxyWithTarget:self] selector:@selector(timerTest) userInfo:nil repeats:YES];
    
    

    或者LProxy直接继承NSProxy来实现消息的方法签名以及消息的转发,

    LProxy.h
    @interface LProxy : NSProxy
    + (instancetype)proxyWithTarget:(id)target;
    @property (nonatomic, weak) id target;
    @end
    
    LProxy.m
    @implementation LProxy
    + (instancetype)proxyWithTarget:(id)target{
        LProxy *proxy = [LProxy alloc];
        proxy.target = target;
        return proxy;
    }
    
    //方法签名
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
        return [self.target methodSignatureForSelector:sel];
    }
    //将方法签名的sel转发为当前的target来进行消息转发
    - (void)forwardInvocation:(NSInvocation *)invocation{
        [invocation invokeWithTarget:self.target];
    }
    
    @end
    

    2.或者直接把NSTimer的创建也放在代理对象实现,通过代理方法把时间间隔以及执行方法暴露给外界使用, 此时也能解决NSTimer循环引用问题。

    3.使用下来方法类进行创建,不对其self进行强引用

    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            
        }];
    

    NSTimer 使用准时吗? 解决方法?

    NSTimer使用不准时,因为NStimer底层是基于NSRunloop的,如果Runloop的任务过于繁重,可能会导致NSTimer不准时,可以使用GCD的定时器,因为GCD定时器不依赖于runloop,它依赖系统内核。

    相关文章

      网友评论

          本文标题:NSTimer 的相关问题

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