首页 > 代码库 > NSTimer解除循环引用

NSTimer解除循环引用

NSTimer作为一个经常使用的类,却有一个最大的弊病,就是会强引用target。造成调用timer很麻烦。稍有不慎就造成内存泄漏。

下面就是为解决问题做的封装。

直接上代码:


#import <Foundation/Foundation.h>


@interface LZLTimer : NSObject


-(void)startTimerInterval:(NSTimeInterval)ti target:aTarget selector:(SEL)selector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;


@end



#import "LZLTimer.h"

@interface LZLWeakTimerTarget : NSObject


@property (nonatomic,weak) id target;

@property (nonatomic,assign) SEL selector;


- (void)timerDidFire:(NSTimer *)timer;


@end


@implementation LZLWeakTimerTarget


- (void)timerDidFire:(NSTimer *)timer {

    if(_target) {

        //消除arc警告

        IMP imp = [_target methodForSelector:_selector];

        if ([NSStringFromSelector(_selector) hasSuffix:@":"]) {

            void (*func)(id, SEL, id) = (void *)imp;

            func(_target, _selector, timer);

        }else {

            void (*func)(id, SEL) = (void *)imp;

            func(_target, _selector);

        }

    } else {

        [timer invalidate];

    }

}


@end


@interface LZLTimer () {

    NSTimer *_timer;

}


@end


@implementation LZLTimer


-(void)dealloc {

    if (_timer!=nil) {

        [_timer invalidate];

        _timer = nil;

    }

}


-(void)startTimerInterval:(NSTimeInterval)ti target:aTarget selector:(SEL)selector userInfo:(id)userInfo repeats:(BOOL)yesOrNo {

    if (nil == _timer) {

        WMWeakTimerTarget *weakTarget = [[WMWeakTimerTarget alloc] init];

        weakTarget.target = aTarget;

        weakTarget.selector = selector;


        _timer = [NSTimer scheduledTimerWithTimeInterval:ti target:weakTarget selector:@selector(timerDidFire:) userInfo:userInfo repeats:yesOrNo];

    }

}


@end


NSTimer解除循环引用