iOS NSTimer导致内存泄露问题

2020-03-17  本文已影响0人  HCL黄

通常情况下

- (void)viewDidLoad {
    [super viewDidLoad];

    self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

- (void)timerAction {
    NSLog(@"timerAction");
    TimerInteger += 1;
    self.label.text = @(TimerInteger).stringValue;
}
- (void)dealloc {
    NSLog(@"dealloc");
    [self.timer invalidate];
    self.timer = nil;
}

然而当我们退出控制器的时候,并不会调用dealloc,导致定时器一直存在,这样就有可能导致内存得不到释放,从而导致内存泄露

通过中间变量来解决这一问题

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LATimerTarget : NSObject

@property (nonatomic, copy) void(^targetBlock)(void);

- (void)timerTargetAction;

@end

NS_ASSUME_NONNULL_END
#import "LATimerTarget.h"

@implementation LATimerTarget

- (void)timerTargetAction {
    NSLog(@"timerTargetAction");
    if (self.targetBlock) {
        self.targetBlock();
    }
}
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.label = [[UILabel alloc] init];
    self.label.backgroundColor = [UIColor greenColor];
    self.label.font = [UIFont systemFontOfSize:20];
    self.label.frame = CGRectMake(0, 100, 200, 100);
    [self.view addSubview:self.label];
    
    /**
     当target为self的时候,退出该控制器时,dealloc是不会调用的,这会导致内存泄露
     */
//    self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
//    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    
    /**
     target设置为LATimerTarget对象,并且在LATimerTarget新增timerTargetAction方法
     通过targetBlock回调,进行UI逻辑处理
     这个时候我们退出该控制器时,dealloc调用,移除定时器
     */
    LATimerTarget *target = [[LATimerTarget alloc] init];
    __weak __typeof(&*self)weakSelf = self;
    target.targetBlock = ^{
        TimerInteger += 1;
        weakSelf.label.text = @(TimerInteger).stringValue;
    };
    self.timer = [NSTimer timerWithTimeInterval:1 target:target selector:@selector(timerTargetAction) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

代码在此

上一篇下一篇

猜你喜欢

热点阅读