博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS定时器循环引用问题解决
阅读量:6219 次
发布时间:2019-06-21

本文共 2289 字,大约阅读时间需要 7 分钟。

hot3.png

我们通常使用NSTimer或CADisplayLink会使用以下方式

//定义@property (nonatomic, strong)NSTimer *timer;//实现self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:proxy selector:@selector(showMsg) userInfo:nil repeats:YES];//销毁-(void)dealloc{    [self.timer invalidate];}

因为控制器强引用了timer,timer又强引用了控制器,所以会产生循环引用。

尝试解决办法:

1、把timer改成弱引用

@property (nonatomic, weak)NSTimer *timer;

虽然控制器对timer是弱引用,但是控制的delloc方法依赖于timer的invalidate,timer的invalidate又依赖于控制器的delloc方法,依旧是循环引用;

2、使用 __weak

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

weak 关键字适用于block,当block引用了块外的变量时,会根据修饰变量的关键字来决定是强引用还是弱引用,如果变量使用weak关键字修饰,那block会对变量进行弱引用,如果没有__weak关键字,那就是强引用。

但是NSTimer的 scheduledTimerWithTimeInterval:target 方法内部不会判断修饰target的关键字,其内部会对target进行强引用,还是会产生循环引用。

最终解决办法

循环引用产生的原因就是因为A强引用B,同时B强引用A,那如果我们在A和B之间加一个C,让A强引用C,C弱引用B,B强引用A,那在B被释放后,A也会释放,就可以解决循环引用的问题;

解决方法1:

定义一个继承自NSObject的类HJProxy,在HJProxy中弱引用target

//HJProxy.h@interface HJProxy : NSObject+(instancetype)proxyWithTarget:(id)target;@end//HJProxy.m#import "HJProxy.h"@interface HJProxy()@property (weak, nonatomic) id target;@end@implementation HJProxy+(instancetype)proxyWithTarget:(id)target{    HJProxy *proxy = [[HJProxy alloc] init];    proxy.target = target;    return proxy;}//使用消息转发,将消息转发给控制器-(id)forwardingTargetForSelector:(SEL)aSelector{    return self.target;}@end
//ViewController.mHJProxy1 *proxy = [HJProxy1 proxyWithTarget:self];//将timer的target设置为proxy,proxy又弱引用了控制器,其实最终还是调用了控制器的showMsg方法。self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:proxy selector:@selector(showMsg) userInfo:nil repeats:YES];

解决方法2:

使用iOS的NSProxy类,NSProxy就是专门用来做消息转发的.

//HJProxy1.h@interface HJProxy1 : NSProxy+(instancetype)proxyWithTarget:(id)target;@end//HJProxy1.m@interface HJProxy1()@property (weak, nonatomic)id target;@end@implementation HJProxy1+(instancetype)proxyWithTarget:(id)target{    HJProxy1 *proxy = [HJProxy1 alloc];    proxy.target = target;    return proxy;}-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel{    return [self.target methodSignatureForSelector:sel];}-(void)forwardInvocation:(NSInvocation *)invocation{    [invocation invokeWithTarget:self.target];}@end

转载于:https://my.oschina.net/mexiaobai1315/blog/1858635

你可能感兴趣的文章
vim常用命令
查看>>
iptables端口安全高级应用
查看>>
Docker配置&LNMP环境搭建
查看>>
使用YUICompressor时出现unterminated string literal的处理
查看>>
曲子龙:不同行业应用区块链到底能够链上啥?
查看>>
achartengine.jar导致不能package的解决办法
查看>>
Spring Cloud与Dubbo共存方案总结
查看>>
Mongodb基操--分片群集操作详解
查看>>
配置文档的访问权限
查看>>
消息总线(Kafka)
查看>>
IP UDP包头详解
查看>>
Kafka连接器深度解读之错误处理和死信队列
查看>>
苹果电脑专业录音软件 电脑如何在线录音
查看>>
DCHP基本配置及中继实验一
查看>>
人工智能、神经网络、深度学习、机器学习傻傻分不清?来看看AI奠基人的解答!...
查看>>
基于 Kafka 实现分布式事件驱动
查看>>
深入浅出大数据分析
查看>>
Android路由框架-ARouter详解
查看>>
Eclipse快捷键大全(转载)
查看>>
众包平台发布一波关于运维开发需求,多少钱由你来报
查看>>