摘要:[iOS]Block與GCD多執行緒運用(一)
如果有寫過.Net windows Form的應用程式,你就會有經驗,在Form程式裡面的UI控制項都是跑在主要的執行緒中。如果要避免當你執行某些動作時,為了解決UI控制項回應時照成的等待,常常會使用到多執行續來處理。而當我們在其他執行緒處理的動作要更新到UI控制項的狀態,就需要呼叫主執行緒裡面的物件來做更新的動作。在.Net裡面會用下列的語法來處理這段。
this.InvokeOnMainThread(() =>{
dosomething ;
});
在iOS的結構上,基本概念是一樣的。只要是跟視覺化有關係的UI控制項,都是執行在主要執行緒。
iOS在多執行緒的處理提供了兩種方式,傳統的NSThread與Grand Center Dispatch。這邊我會用GCD的佇列方式來處理這個範例。
建立一個iOS專案,在View裡面拖拉一個Progress bar。我們要利用這個Progress bar來模擬網路下載資料時的完成度百分比呈現。
在ViewController.h檔案拖拉建立Progress Bar的IBOutlet關聯。接著在宣告一個方法dosomething。
ViewController.h
#import
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIProgressView *myProgress;
-(void)dosomething;
@end
把畫面切到ViewController.m檔案,在這裏先來實作dosomething這個函數的內容。在這個內容之中,我們跑一個迴圈,並且在每次進入這個迴圈的時候,停止一秒鐘,接著去更新iOS畫面上的UI元件,呈現出Progress bar在讀取進度的效果。而在dosomething這個函數要去更新主執行緒中的UI元件狀態時,我們需要去呼叫Main queue來更新元件。
回到ViewDidLoad方法中,在這裡建立一個serial queue。接著執行dispatch_async。在block區域中呼叫dosomething方法。
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.myProgress.progress = 0;
//自訂serial queue
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
//用非同步的方式執行
dispatch_async(myQueue,^{
[self dosomething];
});
NSLog(@"主執行緒結束");
}
-(void)dosomething{
int i;
for (i=0; i<= 10; i+=1) {
[NSThread sleepForTimeInterval:1.0f];
//更新主執行緒上的UI控制項
dispatch_async(dispatch_get_main_queue(), ^{
[self.myProgress setProgress:i*0.1];
});
NSLog(@"%d",i);
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
執行這個App,可以看到模擬器上產生了進度條讀取的效果。
範例檔案下載位置:https://github.com/twbenlu/iOSGCDandBlock