- 循环引用代码
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTest) userInfo:nil repeats:YES];
}
- (void)timerTest {
NSLog(@"%s",__func__);
}
- (void)dealloc {
NSLog(@"%s",__func__);
[self.timer invalidate];
}
@end
- 说明
上述代码中,ViewController强引用Timer,Timer中target为ViewController,会对控制器有一个强引用,产生循环引用。 - 解决方案
1.更换NSTimer初始化方法,使用block方式,__weak修饰target.
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTest) userInfo:nil repeats:YES];
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf timerTest];
}];
}
- (void)timerTest {
NSLog(@"%s",__func__);
}
- (void)dealloc {
NSLog(@"%s",__func__);
[self.timer invalidate];
}
@end
2.使用NSPorxy,中间弱引用对象,打破循环。
创建一个类继承自NSProxy.
.h文件
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface YMProxy : NSProxy
/** target */
@property (nonatomic, weak) id target;
+ (id)proxyWithTarget:(id)target;
@end
NS_ASSUME_NONNULL_END
.m文件
#import "YMProxy.h"
@implementation YMProxy
+ (id)proxyWithTarget:(id)target {
/// 初始化代理对象
YMProxy *proxy = [YMProxy alloc];
proxy.target = target;
return proxy;
}
// 消息转发阶段会调用的方法 当proxy对象找不到控制器中的方法时,会调用这个方法,进行方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.target methodSignatureForSelector:sel];
}
// 方法签名返回值有值的时候,调用此方法 进行消息转发
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.target];
}
@end
ViewController.m
#import "ViewController.h"
#import "YMProxy.h"
@interface ViewController ()
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[YMProxy proxyWithTarget:self] selector:@selector(timerTest) userInfo:nil repeats:YES];
}
- (void)timerTest {
NSLog(@"%s",__func__);
}
- (void)dealloc {
NSLog(@"%s",__func__);
[self.timer invalidate];
}
@end
以上就是NSTimer循环应用解决方案。
网友评论