NSRunLoop

1  NSRunLoop(线程不安全)和CFRunLoopRef(线程安全)


2 苹果不允许直接创建RunLoop, 它只提供两个自动获取的函数

CFRunLoopGetMain() 和 CFRunLoopGetCurrent()


线程和RunLoop之间是一一对应的, 其关系是保存在一个全局的Dictionary里

线程刚创建时,并没有RunLoop, 如果你不主动获取, 那么它一直都不会有

RunLoop的创建是发生在第一次获取时, RunLoop的销毁发生在线程结束时. 你只能在一个线程内部获取其RunLoop


3 一个RunLoop包含若干Mode, 每个Mode又包含若干个Source/Timer/Observer

每次调用RunLoop的主函数时, 只能指定其中一个Mode, 这个Mode被称为CurrentMode. 如果需要切换Mode, 只能退出Loop,在重新指定一个Mode进入


CFRunLoopSourceRef

Source0 只包含了一个回调

Source1 包含了一个mach_port和一个回调

CFRunLoopTimerRef是基于时间的触发器

CFRunLoopObserverRef是观察者


Source/Timer/Observer被统称为mode item, 一个item可以被同时加入多个mode. 一个item被重复加入同一个mode时是不会有效果的, 如果一个mode中一个item都没有,则RunLoop会直接退出


4

struct __CFRunLoopMode {
    CFStringRef _name;            // Mode Name, 例如 @"kCFRunLoopDefaultMode"
    CFMutableSetRef _sources0;    // Set
    CFMutableSetRef _sources1;    // Set
    CFMutableArrayRef _observers; // Array
    CFMutableArrayRef _timers;    // Array
    ...
};
 
struct __CFRunLoop {
    CFMutableSetRef _commonModes;     // Set
    CFMutableSetRef _commonModeItems; // Set
    CFRunLoopModeRef _currentMode;    // Current Runloop Mode
    CFMutableSetRef _modes;           // Set
    ...
};


CommonModes 一个Mode可以将自己标记为Common属性

每当RunLoop的内容发送变化时, RunLoop都会自动将_commonModeItems里的Source/Observer/Timer同步到具有Common标记的所有Mode里


实例:

主线程RunLoop里有两个预置的Mode: kCFRunLoopDefaultMode和UITrackingRunLoopMode.这两个Mode都已经被标记为Common属性

DefaultMode是app平时所处状态, TrackingRunLoopMode是追踪ScrollView滑动状态.

当你创建一个Timer添加到DefaultMode时,Timer会得到重复回调, 但滑动一个tableview时, RunLoop会将mode切换到TrackingRunLoopMode 这时候Timer就不会被调用


解决方法

1. 将Timer添加到两个Mode钟

2.将Timer加入到commonModeItems, commonModeItems被RunLoop自动更新到所有具有Common属性的Mode里去




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值