美文网首页
NSTimer循环引用的问题

NSTimer循环引用的问题

作者: 赑屃王者 | 来源:发表于2021-03-15 16:10 被阅读0次

问题简介

在iOS中,NSTimer的使用非常频繁,但是NSTimer在使用中需要注意,避免循环引用的问题:

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

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

由于self强引用了timer,同时timer也强引用了self,所以循环引用self和timer都不会释放,造成内存泄漏。

一、提前手动释放timer

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
    [self.timer invalidate];
    self.timer = nil;
}

二、timer使用block方式添加Target-Action

需要自己在NSTimer的分类中添加类方法:


+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void (^)(void))block repeats:(BOOL)repeats {
    
    return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(blockSelector:) userInfo:[block copy] repeats:repeats];
}

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

注意:在dealloc时,应该释放timer

三、给self添加中间件proxy

weak指针问题:
用__weak修饰self,做法是无效的。因为无论是weak还是strong修饰,在NSTimer中都会重新生成一个新的强引用指针指向self,导致循环引用的。

原理跟类方法相似,打破循环引用的环路。将timer的target设置为WeakProxy实例,利用消息转发机制实现执行VC中的计时方法,解决循环引用。

创建一个继承NSObject的子类WeakObject,并创建开启计时器的方法。

初始化中间件对象

@interface WeakObject : NSObject

- (instancetype)initWithWeakObject:(id)obj;

+ (instancetype)proxyWithWeakObject:(id)obj;

@end

实现方法

@interface WeakObject()

@property (weak, nonatomic) id weakObject;

@end

@implementation WeakObject

- (instancetype)initWithWeakObject:(id)obj {
    _weakObject = obj;
    return self;
}

+ (instancetype)proxyWithWeakObject:(id)obj {
    return [[WeakObject alloc] initWithWeakObject:obj];
}

仅仅添加了weak类型的属性还不够,为了保证中间件能够响应外部self的事件,需要通过消息转发机制,让实际的响应target还是外部self。
这一步至关重要,涉及到runtime的消息机制。

/// 消息转发,对象转发,让_weakObject响应事件
- (id)forwardingTargetForSelector:(SEL)aSelector {
    return _weakObject;
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    void *null = NULL;
    [invocation setReturnValue:&null];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    return [_weakObject respondsToSelector:aSelector];
}

/// 返回方法的签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    return [NSObject instanceMethodSignatureForSelector:@selector(init)];
}

对象的调用

self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[ZYWeakObject proxyWithWeakObject:self] selector:@selector(timerAction) userInfo:nil repeats:YES];

相关文章

  • ios学记0016-循环引用问题的解决方法

    Block,NSTimer循环引用问题的解决方法 摘要:NSTimer, Block, 循环引用, 内存泄漏 注:...

  • 解决NSTimer循环引用的三种方法

    总结一下项目中遇到的NSTimer循环引用问题 上述方法NSTimer作为属性时会产生循环引用问题,weaksel...

  • ios中循环引用问题

    ios中循环引用问题 NO1: NSTimer 问题:当你创建使用NSTimer的时候,NSTimer会默...

  • Controller销毁NSTimer释放的细节

    关于NSTimer释放和内存泄漏的问题。 @(NSTimer)[内存管理,NSTimer释放,循环引用] 首先需要...

  • iOS定时器循环引用分析及完美解决方案

    目录 1.NSTimer导致的循环引用分析2.NSTimer循环引用解决思路误区3.NSTimer循环引用解决方案...

  • NSTimer的循环引用

    NSTimer基本使用 NSTimer与RunLoop NSTimer 循环引用的问题 如何在子线程使用NSTim...

  • NSTimer 循环引用问题

    题记 在iOS 10系统之前,系统的NSTimer是会引起循环引用的,导致内存泄漏。下面就针对这个问题给出几种解决...

  • NSTimer循环引用问题

    项目中可能会用到NSTimer实现计时器功能,但NSTimer处理不当,会造成循环引用,内存泄漏。通常我们使用NS...

  • NSTimer循环引用问题

    在实际的开发中,在需要定时器时,这样的代码很常见。 那么这样代码如果处理不当,很容易引起循环引用问题。 循环引用产...

  • 4-8 循环引用

    3种循环引用 自循环引用 相互循环引用 多循环引用 Block的循环引用 NSTimer 的循环引用 破除循环引用...

网友评论

      本文标题:NSTimer循环引用的问题

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