= quit); } - NSRunLoop是iOS的消息处理模式, - RunLoop是iOS里线程的一部分,任何线程,包括主线程都包含了一个Run Loop对象。 - NSRunLoop的作用在于有事情做的时候使的当前NSRunLoop的线程工作,没有事情做让当前NSRunLoop的线程休眠。 // 获得当前线程的RunLoop对象 NSRunLoop currentRunLoop]; // 获得主线程的RunLoop对象 [NSRunLoop mainRunLoop]; 一套是Core CFRunLoopObserverRef: 观察者,能够监听RunLoop的状态改 NSRunLoop和CFRunLoopRef都代表着RunLoop对象.NSRunLoop是基于CFRunLoopRef 其中input source分发异步事件给相应的处理程序并且调用runUntilDate:方法(这个方法会在该线程关联的NSRunLoop 对象上被调用)来退出其Run Loop。
众所周知:一个AutoreleasePool对应一个RunLoop,一个RunLoop对应一个线程。但一个RunLoop可以包含多个AutoreleasePool。
must add the timer to a run loop manually by calling the addTimer:forMode: method of the corresponding NSRunLoop must add the timer to a run loop manually by calling the addTimer:forMode: method of the corresponding NSRunLoop .使用timerWithTimerInterval 类方法创建计时器对象没有调度运行循环(RunLoop) 在创建它,必须手动添加计时器运行循环,通过调用adddTimer:forMode:方法相应的NSRunLoop 对象 3.使用initWithFireDate 在创建它,必须手动添加计时器运行循环,通过使用addTimer:forMode:方法相应的NSRunLoop对象 1. - (void)execute { currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run];
, ^{ }); 事件响应、手势识别、界面刷新 网络请求 AutoreleasePool RunLoop 对象 iOS 中有 2 套 API 来访问和使用RunLoop: ① Foundation:NSRunLoop (是CFRunLoopRef的封装,提供了面向对象的 API) ② Core Foundation:CFRunLoopRef NSRunLoop和CFRunLoopRef都代表着RunLoop对象 NSRunLoop不开源,而CFRunLoopRef是开源的:Core Foundation 源码 获取RunLoop对象的方式: // Foundation [NSRunLoop mainRunLoop]; // 获取主线程的 RunLoop 对象 [NSRunLoop currentRunLoop]; // 获取当前线程的 RunLoop 对象 //
timer默认mode, NSRunLoopCommonModes(滑动时主线程会从NSDefaultRunLoopMode切换为UITrackingRunLoopMode,导致timer停止运行) [[NSRunLoop userInfo:userInfo repeats:repeats]; [[NSRunLoop currentRunLoop] addTimer:timerTarget.timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop userInfo:userInfo repeats:repeats]; [[NSRunLoop currentRunLoop] addTimer:timerTarget.timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop
currentRunLoop] addTimer:time forMode:NSDefaultRunLoopMode]; // [[NSRunLoop currentRunLoop] addTimer:time forMode:UITrackingRunLoopMode]; //#else // [[NSRunLoop currentRunLoop] addTimer :time forMode:UITrackingRunLoopMode]; //#else // [[NSRunLoop currentRunLoop] addTimer:time forMode isFinished) { // [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow :0.0001]]; // } // // [[NSRunLoop currentRunLoop] run]; // [time fire]; /
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 2.在子线程中(NSThread开辟新的子线程),使用计时器时 ,需要[[NSRunLoop currentRunLoop] run],(如果NSTimer当前所处的线程正在进行大数据处理(假设为一个大循环),(类似操作列表的滑动过程)使用NSDefaultRunLoopMode timerWithTimeInterval:2.0 target:self selector:@selector(timer_callback) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run]; } }
RunLoop销毁时机:RunLoop会在线程结束时销毁; 主线程的RunLoop已经自动获取(创建),子线程默认没有开启RunLoop; 主线程的RunLoop对象是在UIApplicationMain中通过[NSRunLoop } // HTThread dealloc 开启子线程的 RunLoop 的过程 获取 RunLoop 对象 可以通过以下方式来获取RunLoop对象: // Foundation [NSRunLoop mainRunLoop]; // 获取主线程的 RunLoop 对象 [NSRunLoop currentRunLoop]; // 获取当前线程的 RunLoop 对象 // currentRunLoop] run]; [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate weakSelf.isStoped) { // ③ 启动该 RunLoop /* [[NSRunLoop currentRunLoop
解决方案 定时器的运行需要结合一个 NSRunLoop,同时 NSRunLoop 对该定时器会有一个强引用,这也是为什么我们不对 NSRunLoop 中的定时器进行强引的原因。 由于 NSRunLoop 对定时器有着牵引,那么问题就来了,那么定时器怎样才能被释放掉呢(先不考虑使用removeFromRunLoop:),此时 - invalidate 函数的作用就来了,我们来看看官方就此函数的介绍 据官方介绍可知,- invalidate 做了两件事,首先是把本身(定时器)从 NSRunLoop 中移除,然后就是释放对 target 对象的强引用。从而解决定时器带来的内存泄漏问题。 虽然孤岛问题已经避免了,但还是存在问题,因为 myClock 对象被 UIViewController 以及 timer 引用(timer 直接被 NSRunLoop 强引用着),当 UIViewController 如果对 timer 对象发送一个 invalidate 消息,这样 NSRunLoop 即不会对 timer 进行强引,同时 timer 也会释放对 myClock 对象的强引,这样不就解决了吗?
Runloop 该函数返回一个int类型的值 b 这个默认启动的Runloop是跟主线程相关联的 1.3 RunLoop对象 在iOS开发中有两套api来访问Runloop foundation框架【NSRunloop 】 core foundation框架【CFRunloopRef】 NSRunLoop和CFRunLoopRef都代表着RunLoop对象,它们是等价的,可以互相转换 NSRunLoop是基于CFRunLoopRef NSRunLoop * runloop1 = [NSRunLoop currentRunLoop]; //02 CFRunLoopRef CFRunLoopRef runloop2 = CFRunLoopGetCurrent(); /*2.拿到当前应用程序的主Runloop(主线程对应的Runloop)*/ //01 NSRunloop NSRunLoop ]); } - (void)run { NSLog(@"---run---%@",[NSRunLoop currentRunLoop].currentMode); } - (IBAction
Mode启动,如果当前Mode中没有任Source、Timer、Observer,那么就直接退出RunLoop RunLoop里面有两套api用来访问和使用RunLoop 1、Foundation--NSRunLoop 2、Core Foundation --- CFRunloopRef 二者异同点: NSRunLoop和CFRunloopRef都代表RunLoop对象,NSRunLoop是对CFRunloopRef Foundation */ // 获取当前线程 NSRunLoop *roop = [NSRunLoop currentRunLoop]; // 获取主线程 [NSRunLoop Paste_Image.png // 获取当前Runloop的模式 NSString *runloopMode = [NSRunLoop currentRunLoop].currentMode currentRunLoop] addPort:[NSMachPort port] forMode:NSRunLoopCommonModes]; [[NSRunLoop currentRunLoop
object { @autoreleasepool { [[NSThread currentThread] setName:@"AFNetworking"]; NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode 开启新的线程时,需要维护自动释放池栈 @autoreleasepool { [[NSThread currentThread] setName:@"AFNetworking"]; NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode
NSTimer timerWithTimeInterval:1 target:self selector:@selector(timerThree) userInfo:nil repeats:YES]; [[NSRunLoop :2] interval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { NSLog(@"timer 6"); }]; // iOS 10 [[NSRunLoop ]; // 解决方案二: [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop ] addTimer:timer forMode:UITrackingRunLoopMode]; 子线程的RunLoop没有创建 // 不获取就不会主动创建 NSRunLoop *runLoop = [ NSRunLoop currentRunLoop]; // 保持线程常驻 [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode
timerWithTimeInterval:1.0 target:self selector:@selector(timerUpdate) userInfo:nil repeats:YES]; [[NSRunLoop - (void)timerUpdate { NSLog(@"当前线程:%@",[NSThread currentThread]); NSLog(@"启动RunLoop后--%@",[NSRunLoop currentRunLoop].currentMode); // NSLog(@"currentRunLoop:%@",[NSRunLoop currentRunLoop]); dispatch_async *runLoop = [NSRunLoop currentRunLoop]; NSLog(@"启动RunLoop前--%@",runLoop.currentMode); NSLog(@"currentRunLoop:%@",[NSRunLoop currentRunLoop]); // 第一种写法,改正前 // NSTimer *timer
三、认识NSRunLoop NSRunLoop是Cocoa框架中的类,与之对应,在Core Fundation中是CFRunLoopRef类。 我们这里只来讨论NSRunLoop的属性和方法: + (NSRunLoop *)currentRunLoop; 获取当前线程的RunLoop:有则获取,无则创建 + (NSRunLoop *)mainRunLoop }); } -(void)time{ NSLog(@"run"); } 你会发现,程序运行后并没有打印任何信息,方法并没有被调用,我们必须在线程中手动的执行如下代码: [[NSRunLoop
scheduledTimerWithTimeInterval:timerInterval target:self selector:@selector(handleUpload) userInfo:nil repeats:YES]; [[NSRunLoop scheduledTimerWithTimeInterval:timerInterval target:self selector:@selector(handleUpload) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:self.uploadTimer forMode:NSRunLoopCommonModes]; [[NSRunLoop currentRunLoop
本文Demo传送门 RunloopDemo 前言 OSX / iOS 系统中,提供了两个这样的对象:NSRunLoop 和 CFRunLoopRef。 NSRunLoop 是基于 CFRunLoopRef 的封装,提供了面向对象的 API,但是这些 API 不是线程安全的。 1. 如何查看RunLoop源代码 1.1 NSRunLoop源代码 NSRunLoop是Foundation框架里面的一个类,它的头文件可以在工程里面这样查看: 至于它的实现文件,暂时没有找到公开的资料。 简析RunLoop源代码 2.1 Foundation相关Runloop的源码 NSRunLoop @interface NSRunLoop : NSObject { @private id Foundation NSRunLoop *mainRunloop = [NSRunLoop mainRunLoop]; // 获得主线程对应的 runloop对象 NSRunLoop *currentRunloop
RunLoop 对象和相关类 iOS中有2套API来访问和使用RunLoop: Foundation:NSRunLoop [NSRunLoop currentRunLoop]; // 获得当前线程的 RunLoop对象 [NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象 Core Foundation:CFRunLoopRef CFRunLoopGetCurrent currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] (应用最常见的应该为轮播图自动播放时) 边滚动,定时器边工作,我们就可以用NSRunLoop的默认模式: static int count = 0; NSTimer *timer = currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run
runloop可以理解为cocoa下的一种消息循环机制,用来处理各种消息事件,我们在开发 的时候并不需要手动去创建一个runloop,因为框架为我们创建了一个默认的runloop,通过[NSRunloop NSDefaultRunLoopMode 的消息(因为RunLoop Mode不一样),要想在scrollView滚动的同时也接受其它runloop的消息,我们需要改变两者之间的runloopmode. 1 [[NSRunLoop userInfo:nil repeats:YES]; [[NSRunLoop
二、RunLoop的数据结构 NSRunLoop(Foundation)是CFRunLoop(CoreFoundation)的封装,提供了面向对象的API RunLoop 相关的主要涉及五个类: CFRunLoop 就要用到NSRunLoopCommonModes了 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; Timer 1、为当前线程开启一个RunLoop(第一次调用 NSRunLoop currentRunLoop方法时实际是会先去创建一个RunLoop) 1、向当前RunLoop中添加一个Port/Source等维持 RunLoop的事件循环(如果RunLoop的mode中一个item都没有,RunLoop会退出) 2、启动该RunLoop @autoreleasepool { NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; [[NSRunLoop currentRunLoop] addPort:[NSMachPort port]