逆水行舟 不进则退
今天有个人来公司面试,问了他平时在使用Timer定时器时怎么解决循环引用的问题。然后就得到了这样一个答案:
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:weakSelf selector:@selector(fire) userInfo:nil repeats:YES];
这种方式不能解决循环引用的原因是:在NSTimer的内部会对当前的weakSelf引用计数+1
声明变量
@property (nonatomic, strong, nullable) NSObject *target;
@property (nonatomic, strong, nullable) NSTimer *timer;
第一种:NSTimer提供的API
使用NSTimer提供的API,在block中执行定时任务
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf fire];
}];
引用逻辑
self强引用
timer弱引用
target
第二种: 借助runtime给对象添加消息处理的能力
引用逻辑
self强引用
timer强引用
target
_target = [[NSObject alloc] init];
class_addMethod([_target class], @selector(fire), class_getMethodImplementation([self class], @selector(fire)), "v@:");
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:_target selector:@selector(fire) userInfo:nil repeats:YES];
第三种:通过消息转发的方法的方式
创建一个集成自NSProxy的类PHJProxy 声明一个target
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface PHJProxy : NSProxy
@property (nonatomic, weak) id target;
@end
PHJProxy的实现
@implementation PHJProxy
// 发送给target
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.target];
}
// 给target注册一个方法签名
- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.target methodSignatureForSelector:sel];
}
@end
PHJProxy 和 NSTimer的使用
self.proxy = [PHJProxy alloc];
self.proxy.target = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self.proxy selector:@selector(fire) userInfo:nil repeats:YES];
引用逻辑
self强引用
timer强引用
proxy弱引用
self
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。