Objective-C 多線程


iOS有三種多線程技術:

  • 1.NSThread
    • 創建方式兩種:
      • 1.實例方法:
      • - (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
      • 先創建線程對象,然后再運行線程操作,在運行線程操作前可以設置線程的優先級等線程信息
      • 2.類方法:
      • + (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
      • 直接創建線程並開始運行線程
      • 使用范例:
        • [NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
        • NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];
        • [myThread start];
      • 參數解釋:
      • selector :線程執行的方法,這個selector只能有一個參數,而且不能有返回值。
      • target :selector消息發送的對象
      • argument:傳輸給target的唯一參數,也可以是nil
      • 不顯示創建線程的方法:
      • 調用NSObject的類方法performSelectorInBackground:withObject: 默認在子線程中執行
      • 示范:
        • [Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
      • 示范例子:(子線程異步下載,主線程UI更新)
#import "ViewController.h"
#define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"
@interface ViewController ()


@end


@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];

// [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];
[thread start];
}
-(void)downloadImage:(NSString *) url{
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [[UIImage alloc]initWithData:data];
if(image == nil){

}else{
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];//在主線程中執行(線程間通訊)
}
}
-(void)updateUI:(UIImage*) image{
self.imageView.image = image;
}
@end

 

  • 2.NSOperation
    • 用以封裝執行程序中獨立的工作單元,提供異步執行機制。
    • NSOperation類為抽象類,基於模版方法設計模式
    • Operations可以獨立運行,也可以與Operation Queue協同運行。
    • 使用方式有兩種:
      • 1.用定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation。
      • NSInvocationOperation:
        • 創建方式:
        • NSInvocationOperation* operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(customTaskMethod:)object:params];
      • NSBlockOperation:
        • 創建方式:
        • NSBlockOperation* blockOperation = [NSBlockOperation blockOperationWithBlock: ^{
        • // to do the task.
        • }];
      • 在創建blockOperation后可以調用addExecutionBlock:方法添加更多的block
      • 示范例子:

 

#import "ViewController.h"
#define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self
selector:@selector(downloadImage:)
object:kURL];

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:operation];
// Do any additional setup after loading the view, typically from a nib.
}

-(void)downloadImage:(NSString *)url{
NSLog(@"url:%@", url);
NSURL *nsUrl = [NSURL URLWithString:url];
NSData *data = [[NSData alloc]initWithContentsOfURL:nsUrl];
UIImage * image = [[UIImage alloc]initWithData:data];
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
-(void)updateUI:(UIImage*) image{
self.imageView.image = image;
}

 

      • 2.繼承NSOperation
        • 1.提供一個自定義的初始化方法,在執行operation之前提供初始化流程,准備operation狀態
        • 2.只需繼承重寫NSOperation的一個方法main
        • 3.然后把NSOperation子類的對象放入NSOperationQueue隊列中,該隊列就會啟動並開始處理它
        • 示范例子:
@interface MoveFileOperation : NSOperation

- (id)initWithSrcURL:(NSURL *)srcURL toDestinationURL:(NSURL*)desURL;

@end

// MoveFileOperation.m
@interface MoveFileOperation ()

@property (retain) NSURL *srcURL;

@property (retain) NSURL *desURL;

@end

@implementation MoveFileOperation

@synthesize rootURL, queue;

- (id)initWithSrcURL:(NSURL *)srcURL toDestinationURL:(NSURL*)desURL;
{
self = [super init];
if (self) {
self.srcURL = srcURL;
self.desURL = desURL; 
}
return self;
}

- (void)main
{ 
if ([self isCancelled]){
return;
}
NSDirectoryEnumerator *itr =[[NSFileManager defaultManager] enumeratorAtURL:self.srcURL includingPropertiesForKeys:nil
options:(NSDirectoryEnumerationSkipsHiddenFiles | NSDirectoryEnumerationSkipsPackageDescendants)
errorHandler:nil];
NSError *error = [NSError new];
for (NSURL *url in itr) {
if ([self isCancelled]) {//
break; 
}else{
NSString *fileName = [url lastPathComponent];
NSURL *desFileURL = [self.desURL URLByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] copyItemAtURL:url toURL:desFileURL error:&error];
} 
}
}

 

        • 通過isCancelled方法對operation支持線程取消行為:
        • 常見的正確調用isCancelled的位置包括:
          • 1.在實際執行工作之前
          • 2.在每個循環的執行體中,如果一次執行體耗時很長可酌情添加調用次數
          • 3.程序相對容易終止的代碼處。
        • 配置operation的依賴關系:
          • 調用addDependency: 方法可以建立兩個operation對象間的依賴關系:
          • 這個單向關系表明當前operation對象只有在目標operation對象執行完成之后才能執行。
          • operation對象的依賴關系不限於同一個操作隊列。
          • 有依賴關系的operation對象可以添加到不同的操作隊列中。
          • 但是operation之間不能添加循環依賴關系。
        • 添加Completion Block:
          • 通過setCompletionBlock: 方法可以完成添加completion block的工作,可以在此處派發operation完成的消息。
        • 執行operation的方式:
          • 1 .將operation對象添加到操作隊列NSOperatinQueue對象中:
            • NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
            • 1.// Add a single operation
            • [aQueue addOperation:anOp];
            • 2.// Add multiple operations
            • [aQueue addOperations:anArrayOfOps waitUntilFinished:NO];
            • 3.// Add a block
            • [aQueue addOperationWithBlock:^{
            • /* Do something. */
            • }];
            • NSOperationQueue設計上是用來並發執行operation,setMaxConcurrentOperationCount:方法可以設置操作隊列並行執行的最大數量。
            • 需要設置operation間的依賴關系來保證它們的執行順序是你想要的。
          • 2.手動執行operation:
            • 一個operation只有在其isReady方法返回YES時才被認為是可運行的。
            • isReady方法會被整合進NSOperation的依賴管理系統來保證operation的依賴狀態。
            • 只有在依賴關系清楚后,operation才開始運行。
            • 手動執行operation時,必須調用其start方法。
        • 取消operation:
          • 一旦加入操作隊列,操作隊列就擁有了該operation,並且它不能被刪除。
          • 調出operation的唯一方法是取消(cancel)它
          • 在一個operation上調用cancel可以取消其執行,在操作隊列對象上調用cancelAllOperations 會取消所有operation。
          • operation的取消行為也會被認為是執行完畢(finished),依賴於它的其它operation對象會收到KVO通知來清除該依賴關系。
        • 等待operation結束:
          • 如果創建operation的進程需要處理operation的結果,可以使用NSOperation的 waitUntilFinished方法來阻塞代碼直到operation完成(決不能在主線程上等待一個operation結束)
        • 掛起和回復隊列:
          • 調用NSOperationQueue對象的setSuspended: 方法可以操作隊列掛起。掛起隊列不會阻礙當前正在執行中的operation,它只是阻止新的operation的執行。
  • 3.GCD


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM