当前位置:网站首页>CADisplayLink、NSTimer循环引用解决方案
CADisplayLink、NSTimer循环引用解决方案
2022-07-20 04:23:00 【nginx】
CADisplayLink、NSTimer会对Target产生强引用,如果target又对他们产生强引用,那么就会引发循环引用。
__weak typeof(self) weakSelf = self;能否解决NSTimer的循环引用问题?
@interface ViewController ()
@property (nonatomic, strong) CADisplayLink *link;
@property (nonatomic, strong) NSTimer *time;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 保证调用频率和刷帧频率 60fps
self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(linkTest)];
[self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode] ;
self.time = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeTest) userInfo:nil repeats:YES];
}
- (void)timeTest {
NSLog(@"%s", __func__);
}
- (void)linkTest {
NSLog(@"%s", __func__);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"%s", __func__);
[self.time invalidate];
}
答:我们并不能够通过__weak typeof(self) weakSelf = self;代码来实现解决循环引用。
__weak typeof(self) weakSelf = self;是用在block内可以解决循环引用的问题。
当
方案一、使用 NSTimer 使用 block(CADisplayLink 没有提供block api 不可以用)
NSTime 使用提供 block 的 API ,通过 __weak 解决循序引用问题
方案二、使用 NSObject 消息转发
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
self.time = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf timeTest];
} ];
}
- (void)timeTest {
NSLog(@"%s", __func__);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"%s", __func__);
[self.time invalidate];
}
通过中间变量,是中间的一个引用变成弱引用。
第一步:创建继承 NSObject 的 RHMiddleTarget 中间文件,创建 target 属性,使用 weak 弱引用修饰
第二步:在使用 CADisplayLink 和 NSTimer 中的 target 传到中间变量里:
#import <Foundation/Foundation.h>
@interface RHMiddleTarget : NSObject
@property (nonatomic, weak) id target;
+ (instancetype)middleTargetWithTarget:(id)target;
@end
#import "RHMiddleTarget.h"
@implementation RHMiddleTarget
+ (instancetype)middleTargetWithTarget:(id)target {
RHMiddleTarget *middleTarget = [[RHMiddleTarget alloc] init];
middleTarget.target = target;
return middleTarget;
}
- (id)forwardingTargetForSelector:(SEL)aSelector {
// 返回可以处理的对象, 给对象发送aSelector消息
// objc_msgSend(self.target, aSelector);
return self.target;
}
@end
第三步:测试验证:
// 保证调用频率和刷帧频率 60fps
self.link = [CADisplayLink displayLinkWithTarget:[RHMiddleTarget middleTargetWithTarget:self] selector:@selector(linkTest)];
[self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode] ;
self.time = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[RHMiddleTarget middleTargetWithTarget:self] selector:@selector(timeTest) userInfo:nil repeats:YES];
方案三、使用 NSProxy 消息转发
2022-07-05 16:01:47.895716+0800 Interview03-定时器[10828:260303] -[ViewController timeTest]
2022-07-05 16:01:48.895649+0800 Interview03-定时器[10828:260303] -[ViewController timeTest]
2022-07-05 16:01:49.895571+0800 Interview03-定时器[10828:260303] -[ViewController timeTest]
2022-07-05 16:01:50.666056+0800 Interview03-定时器[10828:260303] -[ViewController touchesBegan:withEvent:]
第一步:创建继承 NSObject 的 RHMiddleTarget 中间文件,创建 target 属性,使用 weak 弱引用修饰
第二步:在使用 CADisplayLink 和 NSTimer 中的 target 传到中间变量里
#import <Foundation/Foundation.h>
@interface RHMiddleTarget : NSProxy
@property (nonatomic, weak) id target;
+ (instancetype)middleTargetWithTarget:(id)target;
@end
#import "RHMiddleTarget.h"
@implementation RHMiddleTarget
+ (instancetype)middleTargetWithTarget:(id)target {
RHMiddleTarget *middleTarget = [RHMiddleTarget alloc];
middleTarget.target = target;
return middleTarget;
}
// 返回方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.target methodSignatureForSelector:sel];
}
// 进行相应的调用
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.target];
}
第三步:测试验证
// 保证调用频率和刷帧频率 60fps
self.link = [CADisplayLink displayLinkWithTarget:[RHMiddleTarget middleTargetWithTarget:self] selector:@selector(linkTest)];
[self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode] ;
self.time = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[RHMiddleTarget middleTargetWithTarget:self] selector:@selector(timeTest) userInfo:nil repeats:YES];
方案四、使用 viewWillDisappear
2022-07-05 16:27:25.427454+0800 Interview03-定时器[11550:281823] -[ViewController linkTest]
2022-07-05 16:27:25.444101+0800 Interview03-定时器[11550:281823] -[ViewController linkTest]
2022-07-05 16:27:25.456983+0800 Interview03-定时器[11550:281823] -[ViewController touchesBegan:withEvent:]
在控制器销毁或者定时器停止的时候,调用如下的方法
[self.timer invalidate];
[self.link invalidate];
self.timer = nil;
self.link = nil;
边栏推荐
- HMS Core音频编辑服务支持7种音频特效,助力一站式音频处理
- Thread pool code and testing
- Apache Flink 的 Per-Job 提交流程
- Detailed decision tree and random forest
- 日期范围生成器
- 买量洞察与渠道评估,助力营销决策优化
- *There are three common ways to obtain reflection: * class C = class Forname ("full class name with package name"); * class C = object. Getclass()/
- Excel怎么转换为Word格式?将Excel转换为Word格式的方法
- EF Core学习笔记:额外的外键属性 / 单项导航属性
- ILRunitme foreach 存在GC
猜你喜欢
何为整型提升(实例)
Qinghai VR fire simulation drill system meets the training needs of many people and scenes
fiddler5+雷电模拟器4.0对app抓包设置
Apache Flink 的 YARN Session 提交流程
精确率和召回率 与 置信度之间的关系
Explain fcos: full revolutionary one stage object detection in detail
Implementation principle of scala function & method and function & method
百家云与美股上市公司富维薄膜达成合并协议,最快于下半年完成合并
Kingdee's "answer sheet" forecast in the first half of the year: key customer strategy continued to break through, and arr increased by more than 45% year-on-year
Get the way to optimize the one-stop worktable of customer service
随机推荐
详解激活函数
虚实相生,构建数智生活|HMS Core. Sparkle应用创新分论坛报名启动
excel怎么选取特定数字求和?excel选中特定数字求和的方法
jdbc error code
计算从今天开始的几天前的日期
typora测试版过期无法正常使用
Relationship between accuracy, recall and confidence
[advanced C language] - detailed explanation of user-defined types
独立站卖家如何利用Facebook主页进行社交媒体营销?
Difi: a go as you pay Wi Fi access system intensive reading notes (III)
excel数据条怎么设置百分比颜色?excel数据条按百分比自动填充颜色教程
Excel宏是什么?Excel宏的使用教程
Apache Flink's yarn session submission process
[pytoch] tensorboard usage: scalar curve, histogram, model structure diagram
Caffeine cache add change check expired
【MUDUO 日志系统1】Logger输出
Inserting data in stored procedures and for loops
A detailed explanation of the implementation principle of go Distributed Link Tracking
The difference between voice message and voice notification in okcc call center
Implementation principle of scala function & method and function & method