使用NSOperation和NSOperationQueue啓動多線程

在app store中的很多應用程序非常的笨重,他們有好的界面,但操作性很差,比如說當程序從網上或本地載入數據的時候,界面被凍結了,用

 

戶只能等程序完全載入數據之後才能進行操作。

當打開一個應用程序時,iphone會產生一個包含main方法的線程,所用程序中的界面都是運行在這個線程之中的(table views, tab bars, 

 

alerts…),有時候我們會用數據填充這些view,現在問        題是如何有效的載入數據,並且用戶還能自如的操作程序。方法是啓動新的線

 

程,專門用於數據的下載,而主線程不會因爲下載數據被阻塞。

不管使用任何編程語言,在實現多線程時都是一件很麻煩的事情。更糟糕的是,一旦出錯,這種錯誤通常相當糟糕。然而,幸運的是apple從os 

 

x10.5在這方面做了很多的改進,NSThread的引入,使得開發多線程應用程序容易多了。除此之外,它們還引入了兩個全新的類,NSOperation和

 

NSOperationQueue。

接下來我們通過一個實例來剖析如何使用這兩個類實現多線程。這裏指示展示這兩個類的基本用法,當然這不是使用他們的唯一辦法。

如果你熟悉java或者它的別的變種語言的話 ,你會發現NSOperation對象很像java.lang.Runnable接口,就像java.lang.Runnable接口那樣,

 

NSOperation類也被設計爲可擴展的,而且只有一個需要重寫的方法。它就是-(void)main。使用NSOperation的最簡單的方式就是把一個

 

NSOperation對象加入到NSOperationQueue隊列中,一旦這個對象被加入到隊列,隊列就開始處理這個對象,直到這個對象的所有操作完成。然

 

後它被隊列釋放。

下面的例子中,使用一個獲取網頁,並對其解析程NSXMLDocument,最後將解析得到的NSXMLDocument返回給主線程。

 

PageLoadOperation.h

@interface PageLoadOperation : NSOperation {

    NSURL *targetURL;}

@property(retain) NSURL *targetURL;

- (id)initWithURL:(NSURL*)url;@end

 

PageLoadOperation.m

#import "PageLoadOperation.h"#import "AppDelegate.h"@implementation PageLoadOperation@synthesize targetURL;- (id)initWithURL:

 

(NSURL*)url;{

    if (![super init]) return nil;

    [self setTargetURL:url];

    return self;}- (void)dealloc {

    [targetURL release], targetURL = nil;

    [super dealloc];

}

- (void)main 

{

    NSString *webpageString = [[[NSString alloc]

    initWithContentsOfURL:[self targetURL]] autorelease];

    NSError *error = nil;

    NSXMLDocument *document = [[NSXMLDocument alloc]

    initWithXMLString:webpageString 

    options:NSXMLDocumentTidyHTML error:&error];

    if (!document) {

        NSLog(@"%s Error loading document (%@): %@", 

        _cmd, [[self targetURL] absoluteString], error);

         return;

    }

    [[AppDelegate shared]

    performSelectorOnMainThread:@selector(pageLoaded:)

         withObject:document waitUntilDone:YES];

    [document release];

}

@end

    正如我們所看到的那樣,這個類相當的簡單,在它的init方法中接受一個url並保存起來,當main函數被調用的時候,它使用這個保存的url

 

創建一個字符串,並將這個字符串傳遞給NSXMLDocumentinit方法。如果加載的xml數據沒有出錯,數據會被傳遞給AppDelegate,它處於主線程

 

中。到此,這個線程的任務就完成了。在主線程中註銷操作隊列的時候,會將這個NSOperation對象釋放。

AppDelegate.h

@interface AppDelegate : NSObject {

    NSOperationQueue *queue;

}+ (id)shared;- (void)pageLoaded:(NSXMLDocument*)document;@endAppDelegate.m        #import "AppDelegate.h"#import 

 

"PageLoadOperation.h"@implementation AppDelegate

static AppDelegate *shared;

static NSArray *urlArray;

- (id)init

{

    if (shared)

    {

        [self autorelease];

        return shared;

    }

    if (![super init]) return nil;    NSMutableArray *array = [[NSMutableArray alloc] init];[array 

 

addObject:@"http://www.google.com"];[array addObject:@"http://www.apple.com"];[array addObject:@"http://www.yahoo.com"];[array 

 

addObject:@"http://www.zarrastudios.com"];[array addObject:@"http://www.macosxhints.com"];urlArray = array;    queue = 

 

[[NSOperationQueue alloc] init];shared = self;return self;

    }

    ?    (void)applicationDidFinishLaunching:

    (NSNotification *)aNotification

{

        for (NSString *urlString in urlArray) 

        {

        NSURL *url = 

        [NSURL URLWithString:urlString];        PageLoadOperation *plo = 

        [[PageLoadOperation alloc] initWithURL:url];

        [queue addOperation:plo];

        [plo release];

        }

}

- (void)dealloc

{

        [queue release], queue = nil;

        [super dealloc];

}

+ (id)shared;

{

        if (!shared) {

            [[AppDelegate alloc] init];

        }

        return shared;

}

- (void)pageLoaded:(NSXMLDocument*)document;

{

        NSLog(@"%s Do something with the XMLDocument: %@",

             _cmd, document);

}

@end

 

NSOperationQueue的並行控制(NSOperationQueue Concurrency)

        在上面這個簡單的例子中,我們很難看出這些操作是並行運行的,然而,如果你你的操作花費的時間遠遠比這裏的要長,你將會發現,

 

隊列是同時執行這些操作的。幸運的是,如果你想要爲隊列限制同時只能運行幾個操作,你可以使用NSOperationQueue的

 

setMaxConcurrentOperationCount:方法。例如,[queue setMaxConcurrentOperationCount:2];

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章