锐客网

iOS-解决NSTimer引起的内存泄漏问题

pop timer所在的控制器,会发现timer还在运行,因为tiemr创建加入了runloop中,如果不主动的调用 invalidate 方法,timer是不会被释放掉的,根本停不下来。
重写dealloc方法,发现pop不走dealloc方法,所以在dealloc中调用invalidate也是没有用的。
控制器要释放掉,则需释放掉所有的实例变量,释放timer,但是释放掉timer则必须释放掉它持有target,由于初始化时timer的target设置为了self,就是当前控制器,所以造成了循环引用,内存泄漏了。
解决办法就是:解除timer对self的强引用,把target替换成单独的对象,再利用消息转发/消息传递使得单独对象中的timer的SEL方法在控制器中实现
方法一:使用NSProxy解决NSTimer内存泄漏问题,利用消息转发来断开NSTimer对象与视图之间的引用关系

@interface TimerProxy : NSProxy- (instancetype)initWithTarget:(id)target; @end

#import "TimerProxy.h"@interface TimerProxy ()@property (nonatomic,weak)id target; @end@implementation TimerProxy- (instancetype)initWithTarget:(id)target {self.target = target; return self; }/* 这个函数让重载方有机会抛出一个函数的签名,再由后面的forwardInvocation:去执行 */ - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { return [self.target methodSignatureForSelector:sel]; }/* 将消息转发给其他对象,这里转发给控制器 */ - (void)forwardInvocation:(NSInvocation *)invocation { SEL sel=[invocation selector]; if ([self.target respondsToSelector:sel]) { [invocation invokeWithTarget:self.target]; } }

【iOS-解决NSTimer引起的内存泄漏问题】使用方法:
- (void)proxy {TimerProxy *proxy=[[TimerProxy alloc]initWithTarget:self]; timer =[NSTimer timerWithTimeInterval:1 target:proxy selector:@selector(timeAction) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop]addTimer:timer forMode:NSRunLoopCommonModes]; } - (void)timeAction { time++; self.timeLabel.text=[NSString stringWithFormat:@"%d",time]; NSLog(@"time%d",time); } - (void)dealloc { [timer invalidate]; }

方法二:使用 消息传递 解决NSTimer内存泄漏问题
创建一个对象,让NSTimer对这个对象进行强引用,而不对控制器进行强引用
@interface WeakTimeObject : NSObject+ (NSTimer *)weakScheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval target:(id)target selector:(SEL)sel userInfo:(id)userInfo repeats:(BOOL)isRepeats; @end

@interface WeakTimeObject ()@property (nonatomic,weak) id target; @property (nonatomic,assign)SEL selector; @end@implementation WeakTimeObject+ (NSTimer *)weakScheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval target:(id)target selector:(SEL)sel userInfo:(id)userInfo repeats:(BOOL)isRepeats {WeakTimeObject *objc=[[WeakTimeObject alloc]init]; objc.target = target; objc.selector = sel; //Nstimer 对 WeakTimeObject 对象 强引用 return [NSTimer scheduledTimerWithTimeInterval:timeInterval target:objc selector:@selector(timeAction:) userInfo:userInfo repeats:isRepeats]; }//消息传递,在 self.target运行 self.selector 方法 - (void)timeAction:(id)info { [self.target performSelector:self.selector withObject:info]; }

使用方法
- (void)objc { timer = [WeakTimeObject weakScheduledTimerWithTimeInterval:1.0 target:self selector:@selector(update) userInfo:nil repeats:YES]; } - (void)update { time++; self.timeLabel.text=[NSString stringWithFormat:@"%d",time]; NSLog(@"time%d",time); }- (void)dealloc { [timer invalidate]; }



    上一篇:陪玩儿&教育

    下一篇:2017.1.2随笔