最近做到一個頁面裡有四個介面,每一個介面返回都有對應的UI改變,所以要四個介面全部請求返回成功後,再去做UI重新整理。然而由於網路請求用的是AFN等第三方庫,本身就是非同步的,所以GCD的柵欄函式dispatch_barrier_async
是沒有用的。
那麼就讓他一個一個的執行,等到所有都執行完成後再去重新整理UI,於是乎呢,可以在第一個網路請求了的返回block裡去做第二個網路請求,以此類推就可以完成最後的UI重新整理。這個不失為一種比較有效的方法,但是這樣寫的程式碼真的挺醜的。。。。
如果單純的想讓這幾個網路請求按順序執行,先進先出,那就是佇列啊,iOS裡提供的佇列管理就是GCD這個強大的c語言實現的庫。GCD裡面有一個訊號量–dispatch_semaphore_t,
dispatch_semaphore_t
dispatch_semaphore_create(long value);
建立一個訊號量,如果value小於0的話,這個訊號量就是nil。
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
可以讓訊號量減1,如果訊號量是0,那麼他會等待訊號量為非零才會執行下一步。
dispatch_semaphore_signal(dispatch_semaphore_t dsema);
可以讓訊號量增加1.
通過這上面的方法,我們可以一開始設計訊號量是0,每一個網路請求之前用dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
,請求結束回撥裡用dispatch_semaphore_signal(dispatch_semaphore_t dsema);
這樣可以讓請求按照順序執行下來。Talk is cheep,show your the code:
- (void)semaphoretest {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(2);
NSLog(@"任務1完成---- %@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(2);
NSLog(@"任務2完成---- %@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(2);
NSLog(@"任務3完成---- %@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
}
複製程式碼
列印結果如下:
很清楚的看到了他們是按照順序執行的。
dispatch_group
最好的設計當然是他們幾個併發執行,到時候全部請求結束後再去做UI的重新整理。於是乎想到了CGD的group啦!GCD就是辣麼強大有木有!設計如下:
- (void)groupTest {
dispatch_queue_t quete = dispatch_queue_create("XIAXIAQUEUE", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_group_async(group, quete, ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(5);
NSLog(@"網路任務1完----%@", [NSThread currentThread]);
dispatch_group_leave(group);
});
sleep(2);
NSLog(@"任務1完成---%@", [NSThread currentThread]);
});
// dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_enter(group);
dispatch_group_async(group, quete, ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(5);
NSLog(@"網路任務2完成----%@", [NSThread currentThread]);
dispatch_group_leave(group);
});
sleep(2);
NSLog(@"任務2完成---%@", [NSThread currentThread]);
});
// dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_enter(group);
dispatch_group_async(group, quete, ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(5);
NSLog(@"網路任務3完成 --- %@", [NSThread currentThread]);
dispatch_group_leave(group);
});
sleep(2);
NSLog(@"任務3完成---- %@", [NSThread currentThread]);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"最後執行 ---- %@", [NSThread currentThread]);
});
}
複製程式碼
列印的結果如下:
首先可以發現其實這幾個任務都是在不同的執行緒的,但是最後執行的肯定是最後一步!
結束語
作為一個程式猿,思考是最重要的,雖然現在網上很多程式碼可以用拿來主義,但是如果只會拿來,那隻能作為一個初級的程式猿了。所以有時候多思考,多想想。