当前位置:网站首页>object-c编程tips-timer「建议收藏」
object-c编程tips-timer「建议收藏」
2022-07-07 20:04:00 【全栈程序员站长】
大家好,又见面了,我是全栈君。
object-c定时器
object-c定时器会自己主动retain当前的使用者,假设不注意调用invalidate,则非常easy引起循环引用导致内存泄露。以下的思路提供了一套还算可行的解决方式。
举例:
常常在viewController中有可能有自己主动刷新界面的需求。 获取数据失败后。每隔10秒自己主动刷新又一次获取数据,这个时候使用NSTimer是一个非常方便的事情。普通情况下直接创建一个NSTimer的repeat对象,然后实现相应的timerFireMethod方法。 当用户主动点击返回button时候,此界面应该被释放。可是因为NSTimer retain了当前的viewController,导致界面内存泄露。 你可能会说在dealloc中调用invalidate,可是必须明确dealloc根本就不会调用,当然viewDidDisappear也一样不会被调用。
前一段时间看了effective object-c,学习了一种非常好的思想,现分享出来。
给NSTimer加入一个类别,使用block的方式传递timerFireMethod。代码例如以下:
@implementation NSTimer(LPBLocks)
+(NSTimer*) lpScheduleTimerWithTimerInternal:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats
{
return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(lpTimerBlockInvoke:) userInfo:[block copy] repeats:repeats];
}
+(void)lpTimerBlockInvoke:(NSTimer*)timer
{
void(^block)() = timer.userInfo;
if(block){
block();
}
}
@end这个scheduledTimer方法也会retain target,可是因为这是一个类方法。它保留的是类对象,因此也就不会有什么问题。
它传入要运行的block, 然后在回调函数中通过userInfo得到block,并运行。
改进:
这个已经是一个非常大的改进了。我们能够在代码中放心的传入block代码。只是细致思考一下。假设在block中引入了viewController的成员,并且timer又作为成员变量存在于viewController中。
比如例如以下的代码:
@interface LPNextViewController ()
{
NSTimer* refreshTimer;
}这样viewController和refreshTimer又陷入了循环引用的逻辑圈里。当然能够在block中使用weak_self的方式避免循环引用,可是写起代码来总是有些不顺手。并且还必需要外部使用者显式的进行。
于是非常easy想到。应该封装到一个专门的LPTimer类中。它负责持有NSTimer。同一时候NSTimer的block使用LPTimer的weak版本号。
@interface LPTimer ()
{
NSTimer* _pollTimer;
//timer selector
__weak id _weak_target;
SEL _selector;
id _userInfo;
}
@end-(void)scheduleTimerWithTimerInternal:(NSTimeInterval)interval
target:(id)target
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)repeats
{
__weak id weak_self = self;
_weak_target = target;
_selector = aSelector;
_userInfo = userInfo;
//借用第一个版本号的block思想
//使用了第二层间接,调用_weak_target的aSelector方法。
//这样能够把stopTimer给封装进去。外部不须要管理timer的stop。
_pollTimer = [NSTimer lpScheduleTimerWithTimerInternal:1 block:^{
[weak_self doTimer];
} repeats:repeats];
}上面的代码LPTimer持有NSTimer对象。而NSTimer运行的block使用的是weak_self。
它在timer触发的时候调用自身的doTimer方法。在doTimer中负责将方法传递给外部的使用者。
-(void)doTimer
{
if ([_weak_target respondsToSelector:_selector]) {
[_weak_target performSelector:_selector withObject:self];
}
else{
DLog(@"WARNNING: unknown selector");
}
}_weak_target是外部的使用者。 外部的使用者能够将LPTimer看成是一个普通的对象即可,持有它也不会有什么问题。 LPTimer保留一个弱引用指向外部的使用者。在时间到timer触发的时候,会先调到NStimer的block中。然后传递到LPTimer的doTimer中。然后调用到_weak_target的selector中。
必须注意释放NStimer对象,在LPTimer释放的时候调用NSTimer的invalidate方法。
-(void)stopTimer
{
DLog(@"");
[_pollTimer invalidate];
}
-(void)dealloc
{
[self stopTimer];
DLog(@"");
}事实上。使用者都是使用的LPTimer类,那么应该让LPTimer表现的和NSTimer的行为一模一样, 使用组合方式的适配器模式就能够轻松搞定。
总结:
主要的思想就是NSTimer会retain一个对象,如今让它retain类对象。
当时候到来进行触发的时候,由NSTimer类对象触发到Block中。继而触发到外部的LPTimer普通对象中。
在普通对象中我们就能够自由的进行处理了。使用weak_target使LPTimer弱引用外部使用者,断开外部使用者与LPTimer的关联。
使用weak_self断开LPTimer与NStimer的循环关联。 个人觉得还算不错的思想, 有须要的欢迎讨论。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116393.html原文链接:https://javaforall.cn
边栏推荐
- Dachang classic pointer written test questions
- 恶魔奶爸 A3阶段 近常速语流初接触
- Spark judges that DF is empty
- Tensorflow2. How to run under x 1 Code of X
- Read PG in data warehouse in one article_ stat
- ERROR: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your
- 九度 1201 -二叉排序数遍历- 二叉排序树「建议收藏」
- You want to kill a port process, but you can't find it in the service list. You can find this process and kill it through the command line to reduce restarting the computer and find the root cause of
- How to choose financial products? Novice doesn't know anything
- openGl超级宝典学习笔记 (1)第一个三角形「建议收藏」
猜你喜欢

Apifox 接口一体化管理新神器

微服务远程Debug,Nocalhost + Rainbond微服务开发第二弹

Small guide for rapid formation of manipulator (12): inverse kinematics analysis

【论文阅读】MAPS: Multi-agent Reinforcement Learning-based Portfolio Management System

How does codesonar help UAVs find software defects?

95年专注安全这一件事 沃尔沃未来聚焦智能驾驶与电气化领域安全

Cantata9.0 | 全 新 功 能

程序猿赚的那点钱算个P啊!

Network principle (1) - overview of basic principles

使用高斯Redis实现二级索引
随机推荐
【函数递归】简单递归的5个经典例子,你都会吗?
When easygbs cascades, how to solve the streaming failure and screen jam caused by the restart of the superior platform?
使用 BR 备份 TiDB 集群数据到 Azure Blob Storage
Nebula importer data import practice
软件缺陷静态分析 CodeSonar 5.2 新版发布
Mrs offline data analysis: process OBS data through Flink job
如何满足医疗设备对安全性和保密性的双重需求?
Write a jump table
2022如何评估与选择低代码开发平台?
Data sorting in string
网络原理(1)——基础原理概述
Micro service remote debug, nocalhost + rainbow micro service development second bullet
Mongodb learn from simple to deep
智能软件分析平台Embold
C语言多角度帮助你深入理解指针(1. 字符指针2. 数组指针和 指针数组 、数组传参和指针传参3. 函数指针4. 函数指针数组5. 指向函数指针数组的指针6. 回调函数)
ISO 26262 - 基于需求测试以外的考虑因素
使用 BR 恢复 Azure Blob Storage 上的备份数据
MySQL约束之默认约束default与零填充约束zerofill
Cantata9.0 | new features
Phoenix JDBC