你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> GCD實戰練習:使用串行隊列實現簡單的預加載

GCD實戰練習:使用串行隊列實現簡單的預加載

編輯:IOS開發基礎

正如使用其它多線程api一樣,使用GCD也可以用於預加載。

本篇使用一個非常簡單的例子來描述怎樣做到預加載一個ViewController,其主要思路是使用gcd在子線程中創建並初始化一個ViewController,在其加載完畢後,將其push入navigation controller中

簡要代碼如下:

@implementation DWClassA
{
    dispatch_queue_t _serialQueue;
    UINavigationController *_navController;
}
 
- (dispatch_queue_t)serialQueue
{
    if (!_serialQueue) {
        _serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);//創建串行隊列
    }
    return _serialQueue;
}
 
- (void)prepareViewController
{
    dispatch_async([self serialQueue], ^{//把block中的任務放入串行隊列中執行,這是第一個任務
        self.viewController = [[[DWViewController alloc] init] autorelease];
        sleep(2);//假裝這個viewController創建起來很花時間。。其實view都還沒加載,根本不花時間。
        NSLog(@"prepared");
    });
}
 
- (void)goToViewController
{
    dispatch_async([self serialQueue], ^{//第二個任務,推入viewController
        NSLog(@"go");
        dispatch_async(dispatch_get_main_queue(), ^{//涉及UI更新的操作,放入主線程中
            [_navController pushViewController:self.viewController animated:YES];
        });
    });
}
 
- (void)dealloc
{
    _serialQueue && dispatch_release(_serialQueue);
    [_navController release];
    [_viewController release];
    [super dealloc];
}
@end

首先我們創建了一個串行隊列(使用DISPATCH_QUEUE_SERIAL作為參數),我們知道,將多個任務dispatch至一個串行隊列,可以達到線程同步的效果,並且可以避免編寫Lock相關的代碼。我們使用一個方法來封裝這個串行隊列的創建,使得後續操作都能取得這個串行隊列

緊接著我們在prepare函數中,將創建並初始化ViewController的任務dispatch至串行隊列中,一旦dispatch,任務將立即開始執行,這裡我使用sleep函數來模擬一個需要較長時間來初始化的viewcontroller,並且sleep了誇張的兩秒鐘。

然後我們在goTo函數中,將push任務dispatch至前述的串行隊列中,當初始化完成後,會自動接著執行push任務,當然,如果dispatch這個push任務時,如果前述的初始化任務早已完成,那麼push任務將被立即執行。值得注意的是,在Cocoa開發中,我們必須將涉及UI更新的操作(即使這個操作不會被立即顯示在屏幕中)放在主線程中執行,這是Apple在文檔中規定的。

實際上Apple規定UIKit的方法都必須放在主線程中調用,事實證明,確實很多不涉及UI操作的UIKit方法都不能在子線程中調用,甚至一些文件加載的函數。而其根本原因是UIKit的這些方法都在內部調用了一些可能產生競態的資源(很多方法會調用render context來進行中間轉換等操作),而一些UIKit方法被驗證確實能放在子線程中調用(雖然不推薦這麼做,因為這麼做不穩定,你不能確定某一天Apple會修改這些方法的內部實現而導致其只能在主線程中執行)也印證了這一點。

最後我們在dealloc函數中釋放應該釋放的資源,注意dispatch_release方法不可以傳入一個NULL指針,這將導致崩潰。

在GCD的頭文件中我們會發現這句注釋:The result of passing NULL in this parameter is undefined.也就是說,不像free函數那樣(free函數由POSIX定義傳入NULL則什麼都不干),dispatch_release是不能接受空指針的。


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved