当前位置:网站首页>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
边栏推荐
- 机械臂速成小指南(十一):坐标系的标准命名
- AADL Inspector 故障树安全分析模块
- OneSpin | 解决IC设计中的硬件木马和安全信任问题
- 201215-03-19—cocos2dx内存管理–具体解释「建议收藏」
- Micro service remote debug, nocalhost + rainbow micro service development second bullet
- Useful win11 tips
- 开发那些事儿:Go加C.free释放内存,编译报错是什么原因?
- 凌云出海记 | 赛盒&华为云:共助跨境电商行业可持续发展
- [concept of network principle]
- 恶魔奶爸 A0 英文零基础的自我提升路
猜你喜欢
95年专注安全这一件事 沃尔沃未来聚焦智能驾驶与电气化领域安全
Implement secondary index with Gaussian redis
软件缺陷静态分析 CodeSonar 5.2 新版发布
How does codesonar help UAVs find software defects?
Tensorflow2.x下如何运行1.x的代码
Small guide for rapid formation of manipulator (11): standard nomenclature of coordinate system
AADL Inspector 故障树安全分析模块
不落人后!简单好用的低代码开发,快速搭建智慧管理信息系统
The latest version of codesonar has improved functional security and supports Misra, c++ parsing and visualization
使用高斯Redis实现二级索引
随机推荐
Nebula importer data import practice
目前股票开户安全吗?可以直接网上开户吗。
九度 1201 -二叉排序数遍历- 二叉排序树「建议收藏」
Micro service remote debug, nocalhost + rainbow micro service development second bullet
论文解读(ValidUtil)《Rethinking the Setting of Semi-supervised Learning on Graphs》
Klocwork 代码静态分析工具
Numerical method for solving optimal control problem (0) -- Definition
恢复持久卷上的备份数据
sqlHelper的增删改查
不落人后!简单好用的低代码开发,快速搭建智慧管理信息系统
想杀死某个端口进程,但在服务列表中却找不到,可以之间通过命令行找到这个进程并杀死该进程,减少重启电脑和找到问题根源。
Implement secondary index with Gaussian redis
基于深度学习的目标检测的更新迭代总结(持续更新ing)
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
刚开户的能买什么股票呢?炒股账户安全吗
使用 BR 备份 TiDB 集群数据到 Azure Blob Storage
使用枚举实现英文转盲文
[award publicity] issue 22 publicity of the award list in June 2022: Community star selection | Newcomer Award | blog synchronization | recommendation Award
目标:不排斥 yaml 语法。争取快速上手
guava多线程,futurecallback线程调用不平均