NSOperationQueue
1,operationQueue 裡邊應該可以同時添加多個operation吧?
是的,本來operationQueue的目的就是多線程管理,那多線程,可不只是一個線程。
而且我們可以設定這個隊列每次被處理的“操作”數量
NSOperationQueue *aQ = [[NSOperationQueue alloc] init];[aQ setMaxConcurrentOperationCount:10];
這裡的setMaxConcurrentOperationCount就是同時被處理的“運算元”,參數為整數int或NSInteger (兩個是一樣的,不記得的可以在我的部落格裡面搜尋一下噢~)
2,那main函數應該怎麼寫?
main函數中其實只需要寫你要在另外一個進程裡面作的事情。比如對於我來說,我常常只是作一個簡單的事情,那我會用NSInvocationOperation,NSOperation的簡化版。比如說:
NSInvocationOperation *aOpt = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomeThing) object:nil]; - (void)doSomeThing{ //讀取大量大延遲資料等等 //可以使用performSelectorOnMainThread來將得來的資料返回到主線程}
在doSomeThing函數裡面,我可以從網上讀取一些東西,但是讀取是需要佔用時間,而堵塞主線程的。而使用NSOperation這樣使用就不會了。
而如果是NSOperation,雖然複雜了一些,又是做一個NSOperation的子類。其實main函數做得事情和doSomeThing是一抹一樣的。只不過如果你製作這個子類,你對其操作的內容可以更多,可以製作更複雜的讀取,載入操作等等,而且你可以重複使用這個類功能阿。再者,NSOperation也提供了對runtime操作的支援,不過那就太麻煩了,一般不大用的上。
NSOperation
多線程編程是防止主線程堵塞,增加運行效率等等的最佳方法。而原始的多線程方法存在很多的毛病,包括線程鎖死等。在Cocoa中,Apple提供了NSOperation這個類,提供了一個優秀的多線程編程方法。
本次講解NSOperation的使用方法:
1,將想在另外一個線程的工作單獨成類,並設定其父類為NSOperation:
@interface ImageLoadingOperation : NSOperation { NSURL *imageURL; //這個例子裡面需要傳入一個圖片地址,所以定義一個NSURL變數 id target; //由於需要返回一些值,所以需要一個對象參數返回要被返回的對象(運行此線程的類對象) SEL action; //傳回值要激發的方法函數}
2,藉由其初始化方法來傳入所需要的參數和對象
- (id)initWithImageURL:(NSURL *)theImageURL target:(id)theTarget action:(SEL)theAction{ self = [super init]; //在老帖裡面解釋過為什麼需要這麼做了 if (self) { imageURL = [theImageURL retain]; // 拷貝進對象,並retain(為什嗎?請查老帖) target = theTarget; action = theAction; } return self;}
呼叫這個類對象的時候,傳入所需要的參數和對象
// 這些是需要對其初始化的類中的代碼ImageLoadingOperation *operation = [[ImageLoadingOperation alloc] initWithImageURL:url target:self action:@selector(didFinishLoadingImageWithResult:)]; //初始化[operationQueue addOperation:operation]; //添加到運行隊列[operation release]; //由於隊列對其retain,所以我們需要release它
3,在我們的線程操作類中的main函數執行所需要的工作
- (void)main{ // 同時載入圖片 NSData *data = [[NSData alloc] initWithContentsOfURL:imageURL]; UIImage *image = [[UIImage alloc] initWithData:data]; // 打包返回給初始類對象,然後執行其指定的操作 NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:image, ImageResultKey, imageURL, URLResultKey, nil]; [target performSelectorOnMainThread:action withObject:result waitUntilDone:NO]; [data release]; //不需要了就清理 [image release];}
這些就是一個簡單的NSOperation的使用過程了。其實看看嘛,非常簡單的,正如蘋果為我們準備的其他API一樣!
NSInvocationOperation
多線程編程是防止主線程堵塞,增加運行效率等等的最佳方法。而原始的多線程方法存在很多的毛病,包括線程鎖死等。在Cocoa中,Apple提供了NSOperation這個類,提供了一個優秀的多線程編程方法。
本次介紹NSOperation的子集,簡易方法的NSInvocationOperation:
@implementation MyCustomClass - (void)launchTaskWithData:(id)data{ //建立一個NSInvocationOperation對象,並初始化到方法 //在這裡,selector參數後的值是你想在另外一個線程中啟動並執行方法(函數,Method) //在這裡,object後的值是想傳遞給前面方法的資料 NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod:) object:data]; // 下面將我們建立的操作“Operation”加入到本地程式的共用隊列中(加入後方法就會立刻被執行) // 更多的時候是由我們自己建立“操作”隊列 [[MyAppDelegate sharedOperationQueue] addOperation:theOp];} // 這個是真正運行在另外一個線程的“方法”- (void)myTaskMethod:(id)data{ // Perform the task.} @end
一個NSOperationQueue 操作隊列,就相當於一個線程管理器,而非一個線程。因為你可以設定這個線程管理器內可以並行啟動並執行的線程數量等等。下面是建立並初始化一個操作隊列:
@interface MyViewController : UIViewController { NSOperationQueue *operationQueue; //在標頭檔中聲明該隊列}@end @implementation MyViewController - (id)init{ self = [super init]; if (self) { operationQueue = [[NSOperationQueue alloc] init]; //初始化操作隊列 [operationQueue setMaxConcurrentOperationCount:1]; //在這裡限定了該隊列只同時運行一個線程 //這個隊列已經可以使用了 } return self;} - (void)dealloc{ [operationQueue release]; //正如Alan經常說的,我們是程式的好公民,需要釋放記憶體! [super dealloc];} @end
簡單介紹之後,其實可以發現這種方法是非常簡單的。很多的時候我們使用多線程僅僅是為了防止主線程堵塞,而NSInvocationOperation就是最簡單的多線程編程,在iPhone編程中是經常被用到的。