文档章节

iOS定时器循环引用问题解决

xiaobai1315
 xiaobai1315
发布于 07/18 11:02
字数 616
阅读 6
收藏 0
iOS

我们通常使用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.m

HJProxy1 *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

© 著作权归作者所有

共有 人打赏支持
xiaobai1315
粉丝 3
博文 200
码字总数 60377
作品 0
程序员
iOS查看屏幕帧数工具--YYFPSLabel

学习 YYKit 代码时,发现 ibireme 在项目里加入的一个查看当前屏幕帧数的小工具,效果如下: 挺实用,实现方法也很简单,但是思路特别棒。 这里是Demo: YYFPSLabel 这里我把这个小工具从 中...

yehot
2016/04/05
0
0
iOS与JS交互之UIWebView-JavaScriptCore框架

级别:★★☆☆☆ 标签:「iOS与JS交互」「UIWebView与JS交互」「JavaScriptCore」 作者: Xs·H 审校: QiShare团队 先解释下标题:“iOS与JS交互”。iOS指原生代码(文章只有示例),JS指前...

QiShare
08/30
0
0
iOS中使用schema协议调用APP和使用iframe打开APP的例子

在iOS中,需要调起一个app可以使用schema协议,这是iOS原生支持的,并且因为iOS系统中都不能使用自己的浏览器内核,所以所有的浏览器都支持,这跟android生态不一样,android是可以自己搞内核...

BearCatYN
2015/06/12
0
1
input 输入框被软键盘遮挡问题

1.安卓手机 在软键盘被弹起来的时候输入框不被遮挡,支持性良好 2.ios手机 在软键盘被弹起来的时候输入框被遮挡,体验很不好 在经过多次实验发现,ios手机输入框被弹起的瞬间是不被遮挡的,过...

爱喝水的小熊
06/06
0
0
iOS与JS交互之WKWebView-WKScriptMessageHandler协议

级别:★★☆☆☆ 标签:「iOS与JS交互」「WKWebView与JS交互」「WKJSMessageHandler」 作者: Xs·H 审校: QiShare团队 先解释下标题:“iOS与JS交互”。iOS指原生代码(文章只有示例),J...

QiShare
09/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何在Java中生成比特币钱包地址

让我们通过学习比特币(Bitcoin)如何实施该技术的各个方面来工作,好吗?该技术包括以下几个方面: 比特币地址bitcoin address是用来发送和接收比特币的。 交易transaction是比特币从一个地...

geek12345
14分钟前
1
0
面试必备Linux基础知识

学习Linux之前,我们先来简单的认识一下操作系统。 一 从认识操作系统开始 1.1 操作系统简介 我通过以下四点介绍什么操作系统: 操作系统(Operation System,简称OS)是管理计算机硬件与软件...

小小明童鞋
14分钟前
5
0
SpringBoot基础教程3-1-3 Quartz定时任务单点持久化

1 概述 实际项目中,复杂的定时任务都会结合持久化,动态改变定时任务状态,本文将介绍基于Quartz的定时任务单点持久化方式,通过RESTful风格,演示定时任务的CRUD,最后使用Swagger测试。 ...

Mkeeper
31分钟前
6
0
Android入门—文件目录解析

AndroidManifest.xml 是每个android程序中必须的文件,它位于整个项目的根目录。我们每天都在使用这个文件,往里面配置程序运行所必要的组件,权限,以及一些相关信息。但是对于这个文件,我...

haoyuehong
34分钟前
8
0
IDEA中Maven打包时如何跳过测试

方法1:直接使用IDEA提供的方式 Maven命令栏的工具栏有下图中的图标,上面就写着 Skip Tests 按下图标后,如下图,test就不可用了 直接使用package命令即可。 方法2:自己编辑maven命令 进入...

karma123
47分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部