当前位置:网站首页>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
边栏推荐
- 寫一下跳錶
- 阿洛的烦恼
- Intelligent software analysis platform embold
- 《数字图像处理原理与实践(MATLAB版)》一书之代码Part2[通俗易懂]
- 201215-03-19—cocos2dx内存管理–具体解释「建议收藏」
- 恶魔奶爸 B2 突破语法,完成正统口语练习
- I wrote a markdown command line gadget, hoping to improve the efficiency of sending documents by garden friends!
- 复杂因子计算优化案例:深度不平衡、买卖压力指标、波动率计算
- Write a jump table
- 95年专注安全这一件事 沃尔沃未来聚焦智能驾驶与电气化领域安全
猜你喜欢
VMWare中虚拟机网络配置
网络原理(1)——基础原理概述
How to meet the dual needs of security and confidentiality of medical devices?
Implement secondary index with Gaussian redis
Nebula importer data import practice
Cantata9.0 | 全 新 功 能
神兵利器——敏感文件发现工具
H3C s7000/s7500e/10500 series post stack BFD detection configuration method
I Basic concepts
软件缺陷静态分析 CodeSonar 5.2 新版发布
随机推荐
VMWare中虚拟机网络配置
How to choose financial products? Novice doesn't know anything
Implement secondary index with Gaussian redis
ISO 26262 - 基于需求测试以外的考虑因素
神兵利器——敏感文件发现工具
凌云出海记 | 赛盒&华为云:共助跨境电商行业可持续发展
Intelligent software analysis platform embold
Implement secondary index with Gaussian redis
想杀死某个端口进程,但在服务列表中却找不到,可以之间通过命令行找到这个进程并杀死该进程,减少重启电脑和找到问题根源。
开发那些事儿:Go加C.free释放内存,编译报错是什么原因?
Micro service remote debug, nocalhost + rainbow micro service development second bullet
I wrote a markdown command line gadget, hoping to improve the efficiency of sending documents by garden friends!
使用 BR 备份 TiDB 集群数据到 Azure Blob Storage
写了个 Markdown 命令行小工具,希望能提高园友们发文的效率!
Lingyun going to sea | saihe & Huawei cloud: jointly help the sustainable development of cross-border e-commerce industry
Lingyun going to sea | yidiantianxia & Huawei cloud: promoting the globalization of Chinese e-commerce enterprise brands
上海交大最新《标签高效深度分割》研究进展综述,全面阐述无监督、粗监督、不完全监督和噪声监督的深度分割方法
C语言 整型 和 浮点型 数据在内存中存储详解(内含原码反码补码,大小端存储等详解)
[concept of network principle]
刚开户的能买什么股票呢?炒股账户安全吗