美文网首页iOS基础知识
iOS 基于消息转发机制实现弱引用计时器

iOS 基于消息转发机制实现弱引用计时器

作者: nullyy | 来源:发表于2018-04-11 22:48 被阅读31次

iOS 基于消息转发机制实现弱引用计时器

在iOS开发中,我们经常使用NSTimer.常使用下列几个方法:

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
...

其中NSTimer示例都会对aTarget进行强持有

@interface NormalViewController ()

@property (nonatomic, strong) NSTimer *timer;

@end

@implementation NormalViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(action) userInfo:nil repeats:YES];
    
}

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

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

上述逻辑如果不主动的指向timer的invalidate方法释放timer中的target, NormalViewControllertimer就构成了循环引用关系
ViewController中我们还好处理,不过有时我们需要在View或者其他对象中来开启计时器,这个时候没有完善的生命周期方法,我们可能完全找不到正确调用timer invalidate方法的时机.
下面使用OC的消息转发机制来实现了一个weak的timer,该方案肯定不是最好方案,不过只是提供一个解决循环引用关系的思路.

自定义WeakTimer基础于NSTimer

@interface WeakTimer : NSTimer

@end


+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo{
    // 将时机Timer的target设置成WeakTimerTarget对象
    WeakTimerTarget *target = [[WeakTimerTarget alloc] init];
    target.aTarget = aTarget;
    target.aSelector = aSelector;
    WeakTimer *timer = [[WeakTimer superclass] scheduledTimerWithTimeInterval:ti target:target selector:aSelector userInfo:userInfo repeats:yesOrNo];
    target.timer = timer;
    return timer;
    
}

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

WeakTimerTarget:

@interface WeakTimerTarget : NSObject

@property (nonatomic, weak) id aTarget;
@property (nonatomic, assign) SEL aSelector;
@property (nonatomic, weak) NSTimer *timer;

@end
@implementation WeakTimerTarget


- (id)forwardingTargetForSelector:(SEL)aSelector{
    
    if (aSelector == _aSelector){
        if (!_aTarget){
            if (_timer){
                [_timer invalidate];
            }
            return [[WeakTimerTargetdonotCrash alloc] init];
        }
        return _aTarget;
    }
    return [super forwardingTargetForSelector:aSelector];
}

@end

  1. WeakTimerTarget对象中会有弱属性aTarget 方法aSelector 并弱引用timer
  2. timer实际会使用WeakTimerTarget对象调用aSelector方法
  3. WeakTimerTarget对象未实现aSelector方法
  4. WeakTimerTarget执行消息转发流程

在消息转发第二部中我们将方法调用转给实际的target - aTarget, 最后结果其实变成了

    [aTarget aSelector]

aTarget对象强引用timer
timer强引用WeakTimerTarget对象
WeakTimerTarget对象弱引用aTarget
打破了循环引用关系
当aTarget被释放的时候,WeakTimerTarget对象中的aTarget == nil
这个时候执行

    [_timer invalidate];

停止timer
这个时候我们在- (id)forwardingTargetForSelector:(SEL)aSelector方法中返回了一个WeakTimerTargetdonotCrash对象
该对象的作用是: 将该步的消息转发流程走完, 并避免此次方法调用导致crash

@interface WeakTimerTargetdonotCrash: NSObject


@end


@implementation WeakTimerTargetdonotCrash


void travel(id self, SEL _cmd){
    NSLog(@"travel");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    // 添加空方法
    class_addMethod([self class], sel, (IMP)travel, "V@:");
    return  YES;
}


@end

该对象其实只做一个简单的事: 在消息转发流程第一步中, 补救WeakTimerTargetdonotCrash对象的未实现方法调用导致的crash

demo

后续为完善demo,使用runtime直接修改NSTimer,将NSTimer改成弱引用类型的计时器.

相关文章

  • iOS 基于消息转发机制实现弱引用计时器

    iOS 基于消息转发机制实现弱引用计时器 在iOS开发中,我们经常使用NSTimer.常使用下列几个方法: 其中N...

  • runtime系列文章总结

    《iOS Runtime详解(消息机制,类元对象,缓存机制,消息转发)》《消息转发机制与Aspects源码解析》《...

  • iOS理解Objective-C中消息转发机制附Demo

    iOS理解Objective-C中消息转发机制附Demo iOS理解Objective-C中消息转发机制附Demo

  • iOS面试-基础

    [toc] Runloop AutoReleasePool 多线程 响应者链 消息响应机制 消息转发机制 iOS内...

  • iOS 消息转发机制

    今天大概学习了下iOS的消息转发机制,还是挺有收获,在此做下笔记,以便后面温习。 1.iOS的消息转发机制原理如下...

  • iOS面试题总结(二)

    iOS面试题(二) 消息发送和转发机制,SEL和IMP 消息发送转载自黄龙辉消息发送和消息转发机制 在Object...

  • Runtime

    相关简单介绍 消息机制消息传递机制消息转发机制-动态添加方法消息转发机制-快速转发消息转发机制-慢速转发消息转发机...

  • iOS - 消息转发机制

    我们知道,OC是动态语言,所有的方法都会以消息的形式传递给对象,对象会根据方法的类型来进行实例方法或者类方法的选择...

  • 【iOS】消息转发机制

    1、动态方法解析 对象在收到无法处理的消息时,会调用下面的方法,前者是调用类方法时会调用,后者是调用对象方法时会调...

  • iOS消息转发机制

    OC消息转发 oc中的调用对象或者类不存在的方法,会执行一遍消息转发流程.消息转发主要包括4步 首先调用+ (BO...

网友评论

    本文标题:iOS 基于消息转发机制实现弱引用计时器

    本文链接:https://www.haomeiwen.com/subject/urrtkftx.html