前语
在开发中难免使用到NSTimer,为了避免循环引用,可能会在willDismiss来进行释放,置为nil;不过经过查阅大神资料,有更好的解决方法:NSProxy;
下面来介绍一下
实现
先上代码:MyTimerProxy.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MyTimerProxy : NSObject
@property (nonatomic, weak) id target;
+ (instancetype)initWithTarget:(id)target;
@end
MyTimerProxy.m
//
// MyTimerProxy.m
// Test-OC
//
// Created by Old.Wang on 2020/11/9.
// Copyright © 2020 Old.Wang. All rights reserved.
//
#import "MyTimerProxy.h"
@implementation MyTimerProxy
+ (instancetype)initWithTarget:(id)target{
MyTimerProxy * proxy = [[MyTimerProxy alloc] init];
proxy.target = target;
return proxy;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
if ([self.target respondsToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:self.target];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
return [self.target methodSignatureForSelector:aSelector];
}
@end
Controller层使用以及日志
#import "ViewController.h"
#import "MyTimerProxy.h"
@interface ViewController ()
@property (nonatomic, strong) NSTimer * t_timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
MyTimerProxy *myProxy = [MyTimerProxy initWithTarget:self];
self.t_timer = [NSTimer timerWithTimeInterval:3 target:myProxy selector:@selector(runTimer) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.t_timer forMode:NSRunLoopCommonModes];
}
#pragma mark - timer
- (void)runTimer{
NSLog(@"Runing %s",__func__);
}
#pragma mark - Dealloc
- (void)dealloc{
[self.t_timer invalidate];
self.t_timer = nil;
NSLog(@"%s",__func__);
}
@end
离开页面栈后,最后打印日志为:[viewController dealloc],对象释放;
原理
实际上通过弱化self - target 的强引用关系来解决引用环。