你好,歡迎來到IOS教程網

 Ios教程網 >> IOS訊息 >> 關於IOS >> iOS開發多線程基礎知識 NSOperation

iOS開發多線程基礎知識 NSOperation

編輯:關於IOS

1.NSOperation的作用

·配合使用NSOperation和NSOperationQueue也能實現多線程編程   2.NSOperation和NSOperationQueue實現多線程的具體步驟 ·先將需要執行的操作封裝到一個NSOperation對象中 ·然後將NSOperation對象添加到NSOperationQueue中 ·系統會自動將NSOperation中封裝的操作放到一條新線程中執行   ---------NSOperation的子類---- 3.NSOperation是個抽象類,並不具備封裝操作的能力,必須使用它的子類   4.使用NSOperation子類的方式有3種 ·NSInvocationOperation ·NSBlockOperation ·自定義子類繼承NSOperation,實現內部相應的方法   ------NSInvocationOperation--- 5.創建NSInvocationOperation對象 - (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;   6.調用start方法開始執行操作 - (void)start;   一旦執行操作,就會調用target的sel方法   7.注意 ·默認情況下,調用了start方法後並不會開一條新線程去執行操作,而是在當前線程同步執行操作 ·只有將NSOperation放到一個NSOperationQueue中,才會異步執行操作     -------NSBlockOperation-- 8.創建NSBlockOperation對象 + (id)blockOperationWithBlock:(void (^)(void))block;   9.通過addExecutionBlock:方法添加更多的操作 - (void)addExecutionBlock:(void (^)(void))block;   注意:只要NSBlockOperation封裝的操作數 > 1,就會異步執行操作       -------NSOperationQueue----   10.NSOperationQueue的作用 ·NSOperation可以調用start方法來執行任務,但默認是同步執行的 ·如果將NSOperation添加到NSOperationQueue(操作隊列)中,系統會自動異步執行NSOperation中的操作   11.添加操作到NSOperationQueue中 - (void)addOperation:(NSOperation *)op;   - (void)addOperationWithBlock:(void (^)(void))block;       -------最大並發數----   12.什麼是並發數 ·同時執行的任務數 ·比如,同時開3個線程執行3個任務,並發數就是3   13.最大並發數的相關方法 - (NSInteger)maxConcurrentOperationCount;   - (void)setMaxConcurrentOperationCount:(NSInteger)cnt;   -----隊列的取消、暫停、恢復------   14.取消隊列的所有操作 - (void)cancelAllOperations;   提示:也可以調用NSOperation的- (void)cancel方法取消單個操作   15.暫停和恢復隊列 - (void)setSuspended:(BOOL)b; // YES代表暫停隊列,NO代表恢復隊列   - (BOOL)isSuspended;   ----操作優先級-----   16.設置NSOperation在queue中的優先級,可以改變操作的執行順序 - (NSOperationQueuePriority)queuePriority;   - (void)setQueuePriority:(NSOperationQueuePriority)p;   17.優先級的取值(優先級越高,越先執行) ·NSOperationQueuePriorityVeryLow = -8L, ·NSOperationQueuePriorityLow = -4L, ·NSOperationQueuePriorityNormal = 0, ·NSOperationQueuePriorityHigh = 4, ·NSOperationQueuePriorityVeryHigh = 8   ---操作依賴--- 18.NSOperation之間可以設置依賴來保證執行順序 ·比如一定要讓操作A執行完後,才能執行操作B,可以這麼寫 [operationB addDependency:operationA]; // 操作B依賴於操作A   19.可以在不同queue的NSOperation之間創建依賴關系   20.注意:不能相互依賴   ·比如A依賴B,B依賴A ----操作的執行順序--- 21.對於添加到queue中的operations,它們的執行順序取決於2點 ·首先依據NSOperation之間的依賴關系 ·然後依據NSOperation的優先級   22.因此,總體的執行順序是 ·先滿足依賴關系 ·然後再從NSOperation中選擇優先級最高的那個執行       ---自定義NSOperation--- 23.自定義NSOperation的步驟很簡單 ·重寫- (void)main方法,在裡面實現想執行的任務   24.重寫- (void)main方法的注意點 ·自己創建自動釋放池(因為如果是異步操作,無法訪問主線程的自動釋放池) ·經常通過- (BOOL)isCancelled方法檢測操作是否被取消,對取消做出響應       --------分割線--- NSOperation小代碼1, 只寫一個文件參考下   //  DYFViewController.m //  624-03-NSOperation // //  Created by dyf on 14-6-24. //  Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. //   #import "DYFViewController.h"   @interface DYFViewController ()   @end   @implementation DYFViewController   - (void)viewDidLoad {     [super viewDidLoad];     // Do any additional setup after loading the view, typically from a nib.               [self testOperationQueue]; }   - (void)testOperationListen {     NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{         NSLog(@"下載圖片1111111%@", [NSThread currentThread]);         // 下載圖片     }];     operation3.completionBlock = ^{         // 下載完圖片後想做的時期     };     // 2.創建隊列     NSOperationQueue *queue = [[NSOperationQueue alloc] init];       [queue addOperation:operation3];   }   - (void)testOperationQueue {     // 1.封裝操作     NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];     NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];           NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{         NSLog(@"1111111%@", [NSThread currentThread]);     }];           [operation3 addExecutionBlock:^{         NSLog(@"222222%@", [NSThread currentThread]);     }];     [operation3 addExecutionBlock:^{         NSLog(@"33333%@", [NSThread currentThread]);     }];     // 2.創建隊列     NSOperationQueue *queue = [[NSOperationQueue alloc] init];     // 5以內,2~3為宜     queue.maxConcurrentOperationCount = 2; #warning 面試題     // 設置操作依賴(一定要在添加到隊列中前設置)     [operation2 addDependency:operation1]; // 執行順序取決於依賴,先執行完operation1再執行operation2 // 注意:不能相互依賴,循環操作           // 3.添加操作到隊列中(自動執行操作,自動開啟線程)     [queue addOperation:operation1];     [queue addOperation:operation2];     [queue addOperation:operation3];           // 取消所有線程     //[queue cancelAllOperations];           // 暫停隊列     //[queue setSuspended:YES];           // 設置操作優先級     //operation1.queuePriority = NSOperationQueuePriorityVeryHigh;             }   - (void)testNSBlockOperation {     // 1.創建操作對象,封裝要執行的任務     NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{         for (int i = 0; i < 11; i++) {             NSLog(@"1111111%@", [NSThread currentThread]);         }     }];     // 任務數在2各以上,就會開線程     [operation addExecutionBlock:^{         for (int i = 0; i < 11; i++) {             NSLog(@"222222%@", [NSThread currentThread]);         }     }];     [operation addExecutionBlock:^{         for (int i = 0; i < 11; i++) {             NSLog(@"33333%@", [NSThread currentThread]);         }     }];       // 2.執行操作     [operation start]; }   - (void)testNSInvocationOperation {     // 1.創建操作對象,封裝要執行的任務     NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];     // 2.執行操作(默認情況下,若操作沒有放到隊列queue中,都是同步執行)     [operation start]; }   - (void)download {     for (int i = 0; i < 11; i++) {         NSLog(@"download-----%@", [NSThread currentThread]);     } }   - (void)run {     for (int i = 0; i < 11; i++) {         NSLog(@"run------%@", [NSThread currentThread]);     } }   @end ----自定義NSOperation---     // //  DYFDownloadOperation.h //  624-05-自定義Operation // //  Created by dyf on 14-6-24. //  Copyright (c) 2014年 dyf. All rights reserved. //   #import <Foundation/Foundation.h>   @class DYFDownloadOperation; @protocol DYFDownloadOperationDelegate <NSObject>   @optional - (void)downloadOperation:(DYFDownloadOperation *)operation didFinishedDownload:(UIImage *)image;   @end   @interface DYFDownloadOperation : NSOperation   @property (nonatomic, copy) NSString *url; @property (nonatomic, strong) NSIndexPath *indexPath;   @property (nonatomic, weak) id<DYFDownloadOperationDelegate> delegate;   @end     // //  DYFDownloadOperation.m //  624-05-自定義Operation // //  Created by dyf on 14-6-24. //  Copyright (c) 2014年 dyf. All rights reserved. //   #import "DYFDownloadOperation.h"   @implementation DYFDownloadOperation /**  *  在main方法中實現具體操作  */ - (void)main {     @autoreleasepool {         if (self.isCancelled) return;         NSURL *imaUrl = [NSURL URLWithString:self.url];         if (self.isCancelled) return;         // 下面這行很耗時         NSData *data = [NSData dataWithContentsOfURL:imaUrl];         if (self.isCancelled) return;         UIImage *image = [UIImage imageWithData:data];         if (self.isCancelled) return;                   // 返回主線程顯示圖片         // 通過代理         if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishedDownload:)]) {             [self.delegate downloadOperation:self didFinishedDownload:image];         }     } }   @end     具體利用MVC模式創建的文件老生常談,只來一個Controller.m文件供參考,數據存儲存在問題,可以改用SDWebImage框架處理   // //  DYFTableViewController.m //  624-05-自定義Operation // //  Created by dyf on 14-6-24. //  Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. //   #import "DYFTableViewController.h" #import "DYFAppModel.h" #import "DYFDownloadOperation.h"   #warning Dictionary基礎知識不太理解,字典的賦值回去看看筆記 @interface DYFTableViewController ()<DYFDownloadOperationDelegate>   @property (nonatomic, strong) NSArray *apps; @property (nonatomic, strong) NSOperationQueue *queue;   /**  *  key:url   value:operation對象  */ @property (nonatomic, strong) NSMutableDictionary *oprations; /**  *  key:url   value:image對象  */ @property (nonatomic, strong) NSMutableDictionary *images;   @end   @implementation DYFTableViewController   #pragma mark - 4個懶加載 - (NSArray *)apps {     if (!_apps) {         NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"];         NSArray *arrayApps = [NSArray arrayWithContentsOfFile:path];                   NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:arrayApps.count];         for (NSDictionary *dict in arrayApps) {             DYFAppModel *appM = [DYFAppModel appWithDict:dict];             [arrayM addObject:appM];         }         _apps = arrayM;     }     return _apps; } - (NSOperationQueue *)queue {     if (!_queue) {         _queue = [[NSOperationQueue alloc] init];         // 設置最大並發線程數,最多同時下載3張圖片         _queue.maxConcurrentOperationCount = 3;     }     return _queue; } - (NSMutableDictionary *)oprations {     if (!_oprations) {         _oprations = [[NSMutableDictionary alloc] init];     }     return _oprations; } - (NSMutableDictionary *)images {     if (!_images) {         _images = [NSMutableDictionary dictionary];     }     return _images; }   - (void)viewDidLoad {     [super viewDidLoad];     // Do any additional setup after loading the view, typically from a nib. }   #pragma mark - 數據源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return self.apps.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {     // 1.創建cell     static NSString *identifier = @"apps";     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];     if (!cell) {         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];     }     // 2.設置cell的數據     DYFAppModel *app = self.apps[indexPath.row];     cell.textLabel.text = app.name;     cell.detailTextLabel.text = app.download;           // 重點是如何從網絡下載圖片傳入cell上面     // 每個url對應一個DYFDownloadOperation對象     // 每個url對應一個image對象     UIImage *image = self.images[app.icon];     if (image) {         // 若緩存中存在圖片         cell.imageView.image = image;     }else     {         // 若緩存中不存在圖片,則圖片要從網上下載         // 設置下載前系統刷出的圖片         cell.imageView.image = [UIImage imageNamed:@"身份證小"];                   // 基礎差,下面這行不太理解         DYFDownloadOperation *operation = self.oprations[app.icon];         if (operation) {             // 若正在下載,則不執行其它操作         }else         {             // 若沒在下載,則創建開始下載的子線程             DYFDownloadOperation *operation = [[DYFDownloadOperation alloc] init];             operation.url = app.icon;             operation.indexPath = indexPath;             operation.delegate = self;             // 添加任務進隊列,異步下載             [self.queue addOperation:operation];             // 基礎差,下面這行不太理解             self.oprations[app.icon] = operation;         }     }           // 3.返回cell     return cell; }   #pragma mark - DYFDownloadOperationDelegate - (void)downloadOperation:(DYFDownloadOperation *)operation didFinishedDownload:(UIImage *)image {     // 1.刪除執行完畢的下載操作     [self.oprations removeObjectForKey:operation.url];     // 若圖片下載好     if (image) {         // 2.將下載好的圖片存入緩存         self.images[operation.url] = image;         // 3.刷新這一行cell的數據         [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];         // 4.將圖片存入沙盒                   // 4.1圖片先轉換為2進制數據         NSData *data = UIImagePNGRepresentation(image);         // 4.2設置沙盒路徑         NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[self.apps[operation.indexPath.row] icon]];         NSLog(@"%@", path);         // 4.3保存data到path中         [data writeToFile:path atomically:YES];     } }   // 開始拖拽時候暫停隊列 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {     [self.queue setSuspended:YES]; } // 停止拖拽的時候重啟隊列 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {     [self.queue setSuspended:NO]; }   @end
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved