弱引用NSTimer对象

来源:互联网 发布:echo linux 写入文件 编辑:程序博客网 时间:2024/04/30 09:53
      

不要忘记 NSTimer 会 retain它的对象,意味着如果你的timer的 target 也是 NSTimer的 拥有者的时候,很容易就进入一个循环引用。

你可以通过一个 代理的delegate来 绕过这个, 这个代理对象拥有这个真正target的 weak 引用。 


@interface TMWeakTimerTarget :NSObject


- (instancetype)initWithTarget:(id)target selector:(SEL)selector;


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


@end


@interface TMWeakTimerTarget()


@property (nonatomic,weak) id target;

@property (nonatomic) SEL selector;


@end


@implementationTMWeakTimerTarget


#pragma mark - Initialization


- (instancetype)initWithTarget:(id)target selector:(SEL)selector {

    if (self = [super init]) {

        _target = target;

        _selector = selector;

    }


    return self;

}


- (id)init {

    return [self initWithTarget:nil selector:nil];

}


#pragma mark - TMWeakTimerTarget


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

    if (self.target) {

        // `performSelector:` would generate a potential leak warning (http://stackoverflow.com/a/7073761/503916)

        objc_msgSend(self.target,self.selector);

    }

    else {

        [timer invalidate];

    }

}


@end


你可以创建一个 NSTimer的 Category ,来更容易的使用这个类

/**

 *  Method that can be used in favor of `scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:` in case the target retains the timer instance. Using the aforementioned method would create a retain cycle in this case.

 */

@interface NSTimer (RetainCyclePrevention)


+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval 

                                 weakTarget:(id)target 

                                   selector:(SEL)selector 

                                   userInfo:(id)userInfo 

                                    repeats:(BOOL)yesOrNo;


@end


@implementationNSTimer (RetainCyclePrevention)


+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval 

                                 weakTarget:(id)target 

                                   selector:(SEL)selector 

                                   userInfo:(id)userInfo 

                                    repeats:(BOOL)yesOrNo {

    return [self scheduledTimerWithTimeInterval:timeInterval 

                                         target:[[TMWeakTimerTarget alloc] initWithTarget:target 

                                                                                 selector:selector] 

                                       selector:@selector(timerDidFire:) 

                                       userInfo:userInfo 

                                        repeats:yesOrNo];

}


@end


0 0
原创粉丝点击