CFRunLoop

10 篇文章 0 订阅

 

Cocoa会涉及到Run Loops的
系统级:

GCD,mach kernel,block,pthread

应用层:

NSTimer,UIEvent,Autorelease,

NSObject(NSDelayedPerforming),

NSObject(NSThreadPerformAddition),

CADisplayLink,CATransition,CAAnimation,

dispatch_get_main_queue()(GCD中dispatch到main queue的block会被dispatch到main RunLoop执行),

NSPort,NSURLConnection,

AFNetworking(这个第三方网络请求框架使用在开启新线程中添加自己的run loop监听事件)

构成

Thread包含一个CFRunLoop,一个CFRunLoop包含一种CFRunLoopMode,mode包含CFRunLoopSource,CFRunLoopTimer和CFRunLoopObserver。

CFRunLoopMode

RunLoop只能运行在一种mode下,如果要换mode当前的loop也需要停下重启成新的。利用这个机制,ScrollView过程中NSDefaultRunLoopMode的mode会切换UITrackingRunLoopMode来保证ScrollView的流畅滑动不受只能在NSDefaultRunLoopMode时处理的事件影响滑动。同时mode还是可定制的。

NSDefaultRunLoopMode:默认,空闲状态
UITrackingRunLoopMode:ScrollView滑动时
UIInitializationRunLoopMode:启动时
NSRunLoopCommonModes:Mode集合 Timer计时会被scrollView的滑动影响的问题可以通过将timer添加到NSRunLoopCommonModes来解决

//将timer添加到NSDefaultRunLoopMode中
[NSTimer scheduledTimerWithTimeInterval:1.0 
  target:self 
  selector:@selector(timerTick:) 
  userInfo:nil 
  repeats:YES];
//然后再添加到NSRunLoopCommonModes里
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 
  target:self 
  selector:@selector(timerTick:) 
  userInfo:nil 
  repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
CFRunLoopTimer

NSTimer是对RunLoopTimer的封装

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;

+ (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel;
- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode;

CFRunLoopSource
source0:处理如UIEvent,CFSocket这样的事件
source1:Mach port驱动,CFMachport,CFMessagePort

CFRunLoopObserver
Cocoa框架中很多机制比如CAAnimation等都是由RunLoopObserver触发的。observer到当前状态的变化进行通知。

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { 
kCFRunLoopEntry = (1UL << 0),
kCFRunLoopBeforeTimers = (1UL << 1), 
kCFRunLoopBeforeSources = (1UL << 2), 
kCFRunLoopBeforeWaiting = (1UL << 5), 
kCFRunLoopAfterWaiting = (1UL << 6), 
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
使用RunLoop的案例

AFNetworking
使用NSOperation+NSURLConnection并发模型都会面临NSURLConnection下载完成前线程退出导致NSOperation对象接收不到回调的问题。
AFNetWorking解决这个问题的方法是按照官方的guidhttps://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/occ/instm/NSURLConnection/initWithRequest:delegate:startImmediately:上写的NSURLConnection的delegate方法需要在connection发起的线程runloop中调用,
于是AFNetWorking直接借鉴了Apple自己的一个Demohttps://developer.apple.com/LIBRARY/IOS/samplecode/MVCNetworking/Introduction/Intro.html的实现方法单独起一个global thread,内置一个runloop,所有的connection都由这个runloop发起,回调也是它接收,不占用主线程,也不耗CPU资源。

+ (void)networkRequestThreadEntryPoint:(id)__unused object { 
  @autoreleasepool {
     [[NSThread currentThread] setName:@"AFNetworking"]; 
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
    [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 
    [runLoop run]; 
  }
}

+ (NSThread *)networkRequestThread { 
  static NSThread *_networkRequestThread = nil; 
  static dispatch_once_t oncePredicate; 
  dispatch_once(&oncePredicate, ^{ 
    _networkRequestThread = [[NSThread alloc] initWithTarget:self 
                selector:@selector(networkRequestThreadEntryPoint:) 
                object:nil]; 
    [_networkRequestThread start]; 
  }); 
  return _networkRequestThread;
}

类似的可以用这个方法创建一个常驻服务的线程。click

TableView中实现平滑滚动延迟加载图片

利用CFRunLoopMode的特性,可以将图片的加载放到NSDefaultRunLoopMode的mode里,这样在滚动UITrackingRunLoopMode这个mode时不会被加载而影响到。

UIImage *downloadedImage = ... ;
[self.avatarImageView performSelector:@selector(setImage:) 
                            withObject:downloadedImage 
                            afterDelay:0 
                            inModes:@[NSDefaultRunLoopMode]];

click

本文摘自 

  1. https://github.com/ming1016/study/wiki/CFRunLoop#%E4%BD%BF%E7%94%A8runloop%E7%9A%84%E6%A1%88%E4%BE%8B
  2. http://blog.ibireme.com/2015/05/18/runloop/#base
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值