標籤:style class blog tar ext color
-------NSOperation簡介----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