NSTimer内存泄漏问题

使用NSTimer的时候可能存储内存泄漏问题,例如:当控制器销毁时,会发现dealloc没有被调用,问题的原因在于timer对控制器对象有强引用,即使是使用了weakSelf


#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.

    __weak typeof(self) weakSelf = self;
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:weakSelf selector:@selector(timerInvoke:) userInfo:nil repeats:YES];
    self.timer = timer;

    self.timer = timer;
    
}


- (void)timerInvoke:(NSTimer *)timer{
    NSLog(@"%s",__func__);
}


- (void)dealloc{
    [self.timer invalidate];
    NSLog(@"%s",__func__);
}


@end

 

如需解决这个问题,就得解决问题的原因timer对target对象的强引用,方式可以修改timer的引用为间接对象target,通过间接对象传递真实监听对象和方法,那么当真实对象的dealloc销毁时,调用[self.timer invalidate]; 那么对象既可以销毁,timer也可以销毁,timer销毁了,间接对象target也就可以销毁.


#import "ViewController.h"

#import "HJTimerTarget.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.

//    __weak typeof(self) weakSelf = self;
//    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:weakSelf selector:@selector(timerInvoke:) userInfo:nil repeats:YES];
//    self.timer = timer;

    NSTimer *timer = [HJTimerTarget scheduledTimerWithTimeInterval:2 target:self selector:@selector(timerInvoke:) userInfo:nil repeats:YES];
    
    self.timer = timer;
    
}


- (void)timerInvoke:(NSTimer *)timer{
    NSLog(@"%s",__func__);
}


- (void)dealloc{
    [self.timer invalidate];
    NSLog(@"%s",__func__);
}


@end
#import <Foundation/Foundation.h>

@interface HWWeakTimerTarget : NSObject

@property (nonatomic, weak) id target;
@property (nonatomic, assign) SEL selector;
@property (nonatomic, weak) NSTimer* timer;

+ (NSTimer *) scheduledTimerWithTimeInterval:(NSTimeInterval)interval
                                      target:(id)aTarget
                                    selector:(SEL)aSelector
                                    userInfo:(id)userInfo
                                     repeats:(BOOL)repeats;


@end
#import "HWWeakTimerTarget.h"


@implementation HWWeakTimerTarget

+ (NSTimer *) scheduledTimerWithTimeInterval:(NSTimeInterval)interval
                                      target:(id)aTarget
                                    selector:(SEL)aSelector
                                    userInfo:(id)userInfo
                                     repeats:(BOOL)repeats {
    HWWeakTimerTarget* timerTarget = [[HWWeakTimerTarget alloc] init];
    timerTarget.target = aTarget;
    timerTarget.selector = aSelector;
    timerTarget.timer = [NSTimer scheduledTimerWithTimeInterval:interval
                                                         target:timerTarget
                                                       selector:@selector(fire:)
                                                       userInfo:userInfo
                                                        repeats:repeats];
    return timerTarget.timer;
}

- (void) fire:(NSTimer *)timer {
    if(self.target) {
        [self.target performSelector:self.selector withObject:timer.userInfo];
    } else {
        [self.timer invalidate];
    }
}


- (void)dealloc{
    NSLog(@"%s",__func__);
}

@end

 运行结果:

-[ViewController timerInvoke:]
-[ViewController timerInvoke:]
-[ViewController timerInvoke:]
-[ViewController timerInvoke:]
-[HJTimerTarget dealloc]
-[ViewController dealloc]

  

原文地址:https://www.cnblogs.com/HJiang/p/7308117.html