2016 - 1- 21 - RunLoop使用(2016-1-24修改一次)(2016 - 1 - 24 再次修改)
一:常駐線程 :當需要一個線程一直處理一些耗時操作時,可以讓它擁有一個RunLoop。具體代碼如下:
? ?1.通過給RunloopMode里加源來保證RunLoop不直接退出。 ?
? 這里有個很重要得知識點,runloop對象如果mode為空得話,會直接返回。在下面這段代碼中的run方法里:
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; // 給RunLoop的Mode里添加內容 [[NSRunLoop currentRunLoop] run];// 開啟RunLoop,默認是出于Default模式。
? 保證RunLoop對象的mode不會為空,也就是不會直接退出,保證線程持續運行。
@interface ViewController () @property (nonatomic, strong) ZZThread *testThread;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// 創建自己的線程,并讓其執行run方法ZZThread *thread = [[ZZThread alloc] initWithTarget:self selector:@selector(run) object:nil];self.testThread = thread;[self.testThread start];} - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {[self performSelector:@selector(test) onThread:self.testThread withObject:nil waitUntilDone:NO ]; } - (void)test{NSLog(@"%s ------- %@",__func__,[NSThread currentThread]); } // 給線程添加一個RunLoop 讓線程"Live" - (void)run {NSLog(@"%s -------------- %@",__func__,[NSThread currentThread]);// 如果RunLoop的Mode內沒有內容,RunLoop會被直接銷毀[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; // 給RunLoop的Mode里添加內容 [[NSRunLoop currentRunLoop] run];// 開啟RunLoop,默認是出于Default模式。 NSLog(@"-------------run end -----------");// 正面run方法一直沒有結束 }@end
? 2.給Runloop中添加定時器也可以保證RunLoop直接退出。
- (void)viewDidLoad {[super viewDidLoad];// 創建自己的線程,并讓其執行run方法ZZThread *thread = [[ZZThread alloc] initWithTarget:self selector:@selector(test2) object:nil];self.testThread = thread;[self.testThread start];}- (void)test2{NSTimer *timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(test) userInfo:nil repeats:YES];[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode ];[[NSRunLoop currentRunLoop] run];} - (void)test{NSLog(@"%s ------- %@",__func__,[NSThread currentThread]); }
二:自動釋放池
? 1.RunLoop的自動釋放池的生命周期
??
? RunLoop在開始步驟1時會創建自動釋放池,并將之后的需要創建的臨時對象都放在池子里,然后在步驟6的時候會將池子銷毀,也就是對所有對象做一次realease操作。
也就是說RunLoop每跑一圈,到休眠這個周期里,自動釋放池的生命周期同時也是從創建到銷毀。
? 2016-1-24補充:
? ? Runloop內部是通過注冊一個Observer監聽RunLoop的狀態,當監聽到RunLoop的狀態為before waiting時,就會釋放自動釋放池。(kCFRunLoopBeforeWaiting)?
? ? 需要注意的是,Observer也會在這個時候在執行完銷毀自動釋放池的操作后,再創建一個自動釋放池,而不是在步驟1。?
? ?也就是說RunLoop中的自動釋放池都是在步驟6中銷毀與創建的!!!
? 2016 - 1- 24 16:00再次補充:
? ?可以打印出Runloop對象,發現它內部監聽自動釋放池的obserer對象的activities的值為1和160(32 + 128)
? ?也就是說observer對象其實監聽了Runloop的三個狀態:kCFRunLoopEntry,kCFRunLoopBeforeWaiting,kCFRunLoopExit
? ?kCFRunLoopEntry:Runloop的進入狀態,此時會第一次創建自動釋放池
? ?kCGRunLoopBeforeWaiting: RunLoop的休眠狀態前,此時會銷毀第一次在進入時創建的自動釋放池并又創建一個新的自動釋放池。
? ?kCFRunLoopExit: 直接銷毀自動釋放池
?
?
?
? 2.所以在創建RunLoop對象時應該也用一個自動釋放池包住
// 給線程添加一個RunLoop 讓線程"Live" - (void)run {@autoreleasepool {NSLog(@"%s -------------- %@",__func__,[NSThread currentThread]);// 如果RunLoop的Mode內沒有內容,RunLoop會被直接銷毀[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; // 給RunLoop的Mode里添加內容 [[NSRunLoop currentRunLoop] run];// 開啟RunLoop,默認是出于Default模式。 NSLog(@"-------------run end -----------");// 正面run方法一直沒有結束 }}
?
轉載于:https://www.cnblogs.com/BJTUzhengli/p/5148992.html
總結
以上是生活随笔為你收集整理的2016 - 1- 21 - RunLoop使用(2016-1-24修改一次)(2016 - 1 - 24 再次修改)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 换一个保险杠多少钱?
- 下一篇: 鸡肉多少钱啊?