NSTimer中的循环引用

  • 循环引用代码
#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 

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循环应用解决方案。

你可能感兴趣的:(NSTimer中的循环引用)