美文网首页
定时器消息发送

定时器消息发送

作者: 不如养花 | 来源:发表于2020-04-16 21:14 被阅读0次

    定时器

    定时器

    有NSTimer、CADisplayLink、GCD、NSThread(performSelector:afterDelay:)等。

    NSTimer:

    一般情况下准确,但是当runloop中的耗时操作过多,或者runloopmode切换,就会出现误差,mode切换导致的暂停可以通过把加入的mode改为NSCommonMode来消除,
    

    CADisplayLink:

    基于屏幕刷新的周期,一般很准时,每秒刷新60次。本质也是通过runloop 所以runloop选择其他模式或者耗时操作过多时,仍会造成延迟。因为只在屏幕刷新时调用,所以对于需要实时更新的UI (比如进度条)来说,使用CADisplayLink能优化性能,可以减少无谓的计算。

    GCD

    GCD定时器使用了dispatch source,监听系统内核对象并处理。因为直接调用系统方法,所以更加精准,但是缺点时会内存消耗更大

    定时器内存泄漏

    问题1: NSTimer无法释放
    问题2: 控制器无法释放
    解决方案:再把timer设置为nil之前,使用invalidate 。因为invalidate方法会将定时器从RunLoop中移除,同时解除对target等对象的强引用。在dealloc中调用无效,在viewcontroller生命周期中调用更合适。CADisplayLink同理,而GCD定时器则使用dispatch_suspend()。
    ps :生命周期调用:这种情况是可以解决循环引用的问题,内存可以释放,但是又会引来新的问题,当导航控制器push到下一个页面时,当前VC并没有被释放,这时候我们可能并不想销毁NSTimer,我们通常希望VC该销毁的时候,同时销毁NSTimer,所以调用invalidate方法的时机很难找。所以最好的解决方式是使用nsproxy。

    消息转发机制

    objc_msgSend 有三个阶段 消息发送(当前类,父类中查找)、动态方法解析、消息转发

    消息发送:

    在当前类的方法缓存中查找方法,如果没找到,在类的方法列表中找,还没找到就在父类的缓存,父类的方法列表中查找,如果以上任何一步找到了,都加入当前类的缓存中。没找到就进入动态方法解析阶段。

    动态方法解析:

    查看是否有过动态解析 如果有直接消息转发,否则调用+resolveInstanceMethod:/+resolveClassMethod:动态添加方法实现,并标记为已动态解析,重走消息发送流程。

    消息转发

    1.先调用 forwardingTargetForSelector 方法获取新的 target 作为 receiver 重新执行 selector,如果返回值不用空,走消息发送流程。如果返回的内容不合法(为 nil 或者跟旧 receiver 一样),那就进入第二步。
    2.调用 methodSignatureForSelector 获取方法签名后,判断返回类型信息是否正确,再调用 forwardInvocation 执行 NSInvocation 对象,并将结果返回。如果对象没实现 methodSignatureForSelector 方法,进入第三步。
    3.调用 doesNotRecognizeSelector 方法

    NSMethodSignature

    一个NSMethodSignature对象记录着某个方法的返回值类型信息以及参数类型信息

    NSInvocation

    相关文章

      网友评论

          本文标题:定时器消息发送

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