iOS开发系列-定时器强引用问题
2024-08-31 00:21:40
概述
iOS开发中常用的定时器NSTimer
、CADisplayLink
。
NSTimer 和 CADisplayLink 基本使用
NSTimer的创建方法有两个scheduledTimerWithTimeInterval开头另一个直接timerWithTimeInterval
// scheduled开头创建的定时器默认已经添加到RunLoop中
self.timer =[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(testTimer) userInfo:nil repeats:YES];
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(testTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
CADisplayLink创建方法displayLinkWithTarget创建
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(testLink)];
[link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
定时器强引用问题
在开发中在将通常将控制器作为定时器的target。一般我们在控制器的dealloc
方法中停止定时器。
- (void)dealloc
{
[self.timer invalidate];
}
由于将控制器设置为定时器的target,定时器会对控制器做强引用,造成控制器在pop出栈不会销毁,也不会调用控制器的的dealloc的方法,控制器pop后,定时器依然执行。
避免设置target强引用解决方案
方案一
由于NSTimer可以通过block的方式直接设置定时任务可以避免设置target引起的强引用。
[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
// 定时任务
}];
方案二
创建一个代理TimerProxy,将代理作为定时器target。
TimerProxy.h
#import <Foundation/Foundation.h>
@interface HTTimerProxy : NSObject
+ (instancetype)timerProxyWithTaget:(id)target;
@property (nonatomic, weak) id target;
@end
TimerProxy.m
#import "HTTimerProxy.h"
@implementation HTTimerProxy
+ (instancetype)timerProxyWithTaget:(id)target
{
HTTimerProxy *proxy = [[self alloc] init];
proxy.target = target;
return proxy;
}
// 利用runtime的消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector
{
return self.target;
}
@end
NSTimer与CADisplayLink将HTTimerProx作为代理
// scheduled开头创建的定时器默认已经添加到RunLoop中
self.timer =[NSTimer scheduledTimerWithTimeInterval:1.0 target:[HTTimerProxy timerProxyWithTaget:self] selector:@selector(testTimer) userInfo:nil repeats:YES];
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:[HTTimerProxy timerProxyWithTaget:self] selector:@selector(testLink)];
[link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
最新文章
- ubuntu命令
- SQL语言分类
- visual studio 查找/替换对话框
- Android NDK之JNI陷阱
- Chrome插件开发
- 修改LR自带的示例程序端口号
- ThreadLocal的基本原理与实现
- 一个Java对象到底占用多大内存
- KP 佛学禅语
- 【深圳,武汉】一加科技(One Plus)招聘,寻找不...
- JavaScript易错点转载
- vue监听滚动事件,实现滚动监听
- hihoCoder #1043 : 完全背包(板子题)
- RDS和ROS使用小结
- 不错的东西: AutoMapper
- FT 软件项目管理
- ColumnStore完整验证指南之安装与启动停止
- MFC 的资源文件 就是那个后缀名是 .rc的那个
- Java IO流学习总结二:File
- leetcode 中等题(1)