IOS-多线程(NSOperation)
生活随笔
收集整理的這篇文章主要介紹了
IOS-多线程(NSOperation)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?一、基礎(chǔ)用法
1 // 2 // ViewController.m 3 // IOS_0120_NSOperation 4 // 5 // Created by ma c on 16/1/20. 6 // Copyright ? 2016年 博文科技. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 @interface ViewController ()<UITableViewDelegate> 12 13 @property (nonatomic, strong) UIImageView *imageView; 14 15 @end 16 17 @implementation ViewController 18 /* 19 一、簡介 20 1.NSOperation的作用 21 配合使用NSOperation和NSOperationQueue也能實(shí)現(xiàn)多線程編程 22 23 2.NSOperation和NSOperationQueue實(shí)現(xiàn)多線程的具體步驟 24 1>先將需要執(zhí)行的操作封裝到一個(gè)NSOperation對(duì)象中 25 2>然后將NSOperation對(duì)象添加到NSOperationQueue中 26 3>系統(tǒng)會(huì)自動(dòng)將NSOperationQueue中的NSOperation取出來 27 4>將取出的NSOperation封裝的操作放到一條新線程中執(zhí)行 28 29 二、NSOperation的子類 30 1.NSOperation是個(gè)抽象類,并不具備封裝操作的能力,必須使用它的子類 31 32 2.使用NSOperation子類的方式有3種 33 1>NSInvocationOperation 34 2>NSBlockOperation 35 3>自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法 36 37 三、具體使用 38 1.NSInvocationOperation 39 1>創(chuàng)建NSInvocationOperation對(duì)象 40 - (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg; 41 42 2>調(diào)用start方法開始執(zhí)行操作 43 - (void)start; 44 一旦執(zhí)行操作,就會(huì)調(diào)用target的sel方法 45 46 3>注意 47 默認(rèn)情況下,調(diào)用了start方法后并不會(huì)開一條新線程去執(zhí)行操作,而是在當(dāng)前線程同步執(zhí)行操作 48 只有將NSOperation放到一個(gè)NSOperationQueue中,才會(huì)異步執(zhí)行操作 49 50 2.NSBlockOperation 51 1>創(chuàng)建NSBlockOperation對(duì)象 52 + (id)blockOperationWithBlock:(void (^)(void))block; 53 54 2>通過addExecutionBlock:方法添加更多的操作 55 - (void)addExecutionBlock:(void (^)(void))block; 56 57 3>注意:只要NSBlockOperation封裝的操作數(shù) > 1,就會(huì)異步執(zhí)行操作 58 59 三、NSOperationQueue 60 1.NSOperationQueue的作用 61 NSOperation可以調(diào)用start方法來執(zhí)行任務(wù),但默認(rèn)是同步執(zhí)行的 62 如果將NSOperation添加到NSOperationQueue(操作隊(duì)列)中,系統(tǒng)會(huì)自動(dòng)異步執(zhí)行NSOperation中的操作 63 64 2.添加操作到NSOperationQueue中 65 - (void)addOperation:(NSOperation *)op; 66 - (void)addOperationWithBlock:(void (^)(void))block; 67 68 四、最大并發(fā)數(shù) 69 1.什么是并發(fā)數(shù) 70 同時(shí)執(zhí)行的任務(wù)數(shù) 71 比如,同時(shí)開3個(gè)線程執(zhí)行3個(gè)任務(wù),并發(fā)數(shù)就是3 72 73 2.最大并發(fā)數(shù)的相關(guān)方法 74 - (NSInteger)maxConcurrentOperationCount; 75 - (void)setMaxConcurrentOperationCount:(NSInteger)cnt; 76 77 五、隊(duì)列的取消、暫停、恢復(fù) 78 取消隊(duì)列的所有操作 79 - (void)cancelAllOperations; 80 提示:也可以調(diào)用NSOperation的- (void)cancel方法取消單個(gè)操作 81 82 暫停和恢復(fù)隊(duì)列 83 - (void)setSuspended:(BOOL)b; // YES代表暫停隊(duì)列,NO代表恢復(fù)隊(duì)列 84 - (BOOL)isSuspended; 85 86 六、操作優(yōu)先級(jí) 87 1.設(shè)置NSOperation在queue中的優(yōu)先級(jí),可以改變操作的執(zhí)行優(yōu)先級(jí) 88 - (NSOperationQueuePriority)queuePriority; 89 - (void)setQueuePriority:(NSOperationQueuePriority)p; 90 91 2.優(yōu)先級(jí)的取值 92 NSOperationQueuePriorityVeryLow = -8L, 93 NSOperationQueuePriorityLow = -4L, 94 NSOperationQueuePriorityNormal = 0, 95 NSOperationQueuePriorityHigh = 4, 96 NSOperationQueuePriorityVeryHigh = 8 97 98 七、操作的監(jiān)聽 99 1.可以監(jiān)聽一個(gè)操作的執(zhí)行完畢 100 - (void (^)(void))completionBlock; 101 - (void)setCompletionBlock:(void (^)(void))block; 102 103 八、操作的依賴 104 NSOperation之間可以設(shè)置依賴來保證執(zhí)行順序 105 比如一定要讓操作A執(zhí)行完后,才能執(zhí)行操作B,可以這么寫 106 [operationB addDependency:operationA]; // 操作B依賴于操作A 107 可以在不同queue的NSOperation之間創(chuàng)建依賴關(guān)系 108 109 注意:不能相互依賴 比如A依賴B,B依賴A 110 111 九、第三方框架的使用建議 112 1.用第三方框架的目的 113 1> 開發(fā)效率:快速開發(fā),人家封裝好的一行代碼頂自己寫的N行 114 2> 為了使用這個(gè)功能最牛逼的實(shí)現(xiàn) 115 116 2.第三方框架過多,很多壞處(忽略不計(jì)) 117 1> 管理、升級(jí)、更新 118 2> 第三方框架有BUG,等待作者解決 119 3> 第三方框架的作者不幸去世、停止更新(潛在的BUG無人解決) 120 4> 感覺:自己好水 121 122 3.比如 123 流媒體:播放在線視頻、音頻(邊下載邊播放) 124 非常了解音頻、視頻文件的格式 125 每一種視頻都有自己的解碼方式(C\C++) 126 127 4.總結(jié) 128 1> 站在巨人的肩膀上編程 129 2> 沒有關(guān)系,使勁用那么比較穩(wěn)定的第三方框架 130 131 十、SDWebImage 132 1.什么是SDWebImage 133 iOS中著名的牛逼的網(wǎng)絡(luò)圖片處理框架 134 包含的功能:圖片下載、圖片緩存、下載進(jìn)度監(jiān)聽、gif處理等等 135 用法極其簡單,功能十分強(qiáng)大,大大提高了網(wǎng)絡(luò)圖片的處理效率 136 國內(nèi)超過90%的iOS項(xiàng)目都有它的影子 137 2.項(xiàng)目地址 138 https://github.com/rs/SDWebImage 139 140 1> 常用方法 141 - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; 142 - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options; 143 - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; 144 - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; 145 146 2> 內(nèi)存處理:當(dāng)app接收到內(nèi)存警告時(shí) 147 當(dāng)app接收到內(nèi)存警告 148 - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application 149 { 150 SDWebImageManager *mgr = [SDWebImageManager sharedManager]; 151 152 // 1.取消正在下載的操作 153 [mgr cancelAll]; 154 155 // 2.清除內(nèi)存緩存 156 [mgr.imageCache clearMemory]; 157 } 158 3> SDWebImageOptions 159 * SDWebImageRetryFailed : 下載失敗后,會(huì)自動(dòng)重新下載 160 * SDWebImageLowPriority : 當(dāng)正在進(jìn)行UI交互時(shí),自動(dòng)暫停內(nèi)部的一些下載操作 161 * SDWebImageRetryFailed | SDWebImageLowPriority : 擁有上面2個(gè)功能 162 163 十一、自定義NSOperation 164 自定義NSOperation的步驟很簡單 165 重寫- (void)main方法,在里面實(shí)現(xiàn)想執(zhí)行的任務(wù) 166 167 重寫- (void)main方法的注意點(diǎn) 168 自己創(chuàng)建自動(dòng)釋放池(因?yàn)槿绻钱惒讲僮?#xff0c;無法訪問主線程的自動(dòng)釋放池) 169 經(jīng)常通過- (BOOL)isCancelled方法檢測操作是否被取消,對(duì)取消做出響應(yīng) 170 171 */ 172 173 - (void)viewDidLoad { 174 [super viewDidLoad]; 175 176 // [self useNSInvocationOperation]; 177 // [self useBaseNSBlockOperation]; 178 // [self useNSBlockOperation]; 179 // [self useNSOperationQueue]; 180 // [self useAddDependency]; 181 182 self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(30, 200, 340, 200)]; 183 [self.view addSubview:self.imageView]; 184 [self communicate]; 185 186 } 187 188 #pragma mark - 通訊 189 - (void)communicate 190 { 191 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 192 //取消隊(duì)列所有操作 193 // [queue cancelAllOperations]; 194 // NSLog(@"didCancelAllOperations"); 195 //暫停隊(duì)列 196 [queue setSuspended:YES]; 197 //恢復(fù)隊(duì)列 198 [queue setSuspended:NO]; 199 //異步下載圖片 200 [queue addOperationWithBlock:^{ 201 NSURL *url = [NSURL URLWithString:@"http://images.haiwainet.cn/2016/0113/20160113015030150.jpg"]; 202 NSData *data = [[NSData alloc] initWithContentsOfURL:url]; 203 UIImage *image = [UIImage imageWithData:data]; 204 //回到主線程,顯示圖片 205 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 206 self.imageView.image = image; 207 }]; 208 }]; 209 } 210 211 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 212 { 213 // [queue setSuspended:YES]; //暫停隊(duì)列中所有任務(wù) 214 } 215 216 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 217 { 218 // [queue setSuspended:NO]; //恢復(fù)隊(duì)列中所有任務(wù) 219 } 220 221 #pragma mark - 依賴 222 - (void)useAddDependency 223 { 224 /*三個(gè)異步執(zhí)行操作:操作C依賴于操作B,操作B依賴于操作A*/ 225 226 //創(chuàng)建一個(gè)隊(duì)列 227 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 228 229 NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{ 230 NSLog(@"A1--------%@",[NSThread currentThread]); 231 }]; 232 [operationA addExecutionBlock:^{ 233 NSLog(@"A2--------%@",[NSThread currentThread]); 234 }]; 235 [operationA setCompletionBlock:^{ 236 NSLog(@"依賴于A--------%@",[NSThread currentThread]); 237 238 }]; 239 NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{ 240 NSLog(@"B--------%@",[NSThread currentThread]); 241 }]; 242 NSBlockOperation *operationC = [NSBlockOperation blockOperationWithBlock:^{ 243 NSLog(@"C--------%@",[NSThread currentThread]); 244 }]; 245 //設(shè)置依賴 246 [operationB addDependency:operationA]; 247 [operationC addDependency:operationB]; 248 249 [queue addOperation:operationA]; 250 [queue addOperation:operationB]; 251 [queue addOperation:operationC]; 252 } 253 254 #pragma mark - 隊(duì)列中直接添加任務(wù) 255 - (void)useNSOperationQueue 256 { 257 //1.創(chuàng)建operation的時(shí)候,添加一個(gè)任務(wù) 258 NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ 259 NSLog(@"--------下載圖片1--------%@",[NSThread currentThread]); 260 }]; 261 NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ 262 NSLog(@"--------下載圖片2--------%@",[NSThread currentThread]); 263 }]; 264 265 //2.創(chuàng)建隊(duì)列(非主隊(duì)列)會(huì)自動(dòng)異步執(zhí)行任務(wù),并發(fā) 266 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 267 268 //3.設(shè)置最大并發(fā)數(shù) 269 queue.maxConcurrentOperationCount = 2; 270 271 //4.添加操作到隊(duì)列中 272 [queue addOperation:operation1]; 273 [queue addOperation:operation2]; 274 275 [queue addOperationWithBlock:^{ 276 NSLog(@"--------下載圖片3--------%@",[NSThread currentThread]); 277 }]; 278 } 279 280 #pragma mark - 多操作添加到隊(duì)列 281 - (void)useNSBlockOperation 282 { 283 //創(chuàng)建operation的時(shí)候,添加一個(gè)任務(wù) 284 NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ 285 NSLog(@"--------下載圖片1--------%@",[NSThread currentThread]); 286 }]; 287 NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ 288 NSLog(@"--------下載圖片2--------%@",[NSThread currentThread]); 289 }]; 290 //創(chuàng)建隊(duì)列 291 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 292 //主隊(duì)列 293 // NSOperationQueue *queue = [NSOperationQueue mainQueue]; 294 //添加操作到隊(duì)列中 295 [queue addOperation:operation1]; 296 [queue addOperation:operation2]; 297 298 //[operation start]; 299 } 300 301 #pragma mark - NSBlockOperation 302 - (void)useBaseNSBlockOperation 303 { 304 //創(chuàng)建operation的時(shí)候,添加一個(gè)任務(wù) 305 // NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 306 // NSLog(@"--------下載圖片1--------%@",[NSThread currentThread]); 307 // }]; 308 309 NSBlockOperation *operation = [[NSBlockOperation alloc] init]; 310 //操作中添加任務(wù) 311 [operation addExecutionBlock:^{ 312 NSLog(@"--------下載圖片2--------%@",[NSThread currentThread]); 313 }]; 314 [operation addExecutionBlock:^{ 315 NSLog(@"--------下載圖片3--------%@",[NSThread currentThread]); 316 }]; 317 318 //任務(wù)大于1,才會(huì)異步執(zhí)行 319 [operation start]; 320 } 321 322 #pragma mark - NSInvocationOperation 323 - (void)useNSInvocationOperation 324 { 325 //創(chuàng)建隊(duì)列 326 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 327 //創(chuàng)建操作 328 NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil]; 329 330 //opreation直接調(diào)用start,是同步執(zhí)行(在當(dāng)前線程執(zhí)行操作) 331 //[operation start]; 332 333 //添加操作到隊(duì)列中,會(huì)自動(dòng)異步執(zhí)行 334 [queue addOperation:operation]; 335 } 336 337 - (void)download 338 { 339 NSLog(@"download-------%@",[NSThread currentThread]); 340 } 341 342 - (void)didReceiveMemoryWarning { 343 [super didReceiveMemoryWarning]; 344 // Dispose of any resources that can be recreated. 345 } 346 347 @end?二、防止重復(fù)下載,與沙盒緩存
1 // 2 // BWApp.h 3 // IOS_0120_NSOperation防止重復(fù)下載 4 // 5 // Created by ma c on 16/1/20. 6 // Copyright ? 2016年 博文科技. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface BWApp : NSObject 12 13 @property (nonatomic, copy) NSString *name; 14 @property (nonatomic, copy) NSString *download; 15 @property (nonatomic, copy) NSString *icon; 16 17 + (instancetype)appWithDict:(NSDictionary *)dict; 18 19 @end 20 21 // 22 // BWApp.m 23 // IOS_0120_NSOperation防止重復(fù)下載 24 // 25 // Created by ma c on 16/1/20. 26 // Copyright ? 2016年 博文科技. All rights reserved. 27 // 28 29 #import "BWApp.h" 30 31 @implementation BWApp 32 33 + (instancetype)appWithDict:(NSDictionary *)dict 34 { 35 BWApp *app = [[self alloc] init]; 36 [app setValuesForKeysWithDictionary:dict]; 37 return app; 38 } 39 40 @end 1 // 2 // BWTableViewController.m 3 // IOS_0120_NSOperation防止重復(fù)下載 4 // 5 // Created by ma c on 16/1/20. 6 // Copyright ? 2016年 博文科技. All rights reserved. 7 // 8 9 #import "BWTableViewController.h" 10 #import "BWApp.h" 11 12 #define appImageCachesPath(url) [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[url lastPathComponent]] 13 14 @interface BWTableViewController () 15 16 //所有應(yīng)用數(shù)據(jù) 17 @property (nonatomic, strong) NSMutableArray *appsArray; 18 //存放所有下載操作的隊(duì)列 19 @property (nonatomic, strong) NSOperationQueue *queue; 20 //存放所有下載操作(url是key,operation對(duì)象是value) 21 @property (nonatomic, strong) NSMutableDictionary *operationDict; 22 //緩存圖片 23 @property (nonatomic, strong) NSMutableDictionary *imageDict; 24 25 @end 26 27 @implementation BWTableViewController 28 29 #pragma mark - 懶加載 30 - (NSMutableArray *)appsArray 31 { 32 if (!_appsArray) { 33 NSMutableArray *appArr = [[NSMutableArray alloc] init]; 34 35 NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"]; 36 37 NSArray *dictArr = [NSArray arrayWithContentsOfFile:path]; 38 39 for (NSDictionary *dict in dictArr) { 40 41 BWApp *app = [BWApp appWithDict:dict]; 42 [appArr addObject:app]; 43 } 44 _appsArray = appArr; 45 } 46 return _appsArray; 47 } 48 49 - (NSOperationQueue *)queue 50 { 51 if (!_queue) { 52 _queue = [[NSOperationQueue alloc] init]; 53 } 54 return _queue; 55 } 56 57 - (NSMutableDictionary *)operationDict 58 { 59 if (!_operationDict) { 60 _operationDict = [[NSMutableDictionary alloc] init]; 61 } 62 return _operationDict; 63 } 64 65 - (NSMutableDictionary *)imageDict 66 { 67 if (!_imageDict) { 68 _imageDict = [[NSMutableDictionary alloc] init]; 69 } 70 return _imageDict; 71 } 72 73 #pragma mark - 初始化 74 - (void)viewDidLoad { 75 [super viewDidLoad]; 76 77 } 78 79 - (void)didReceiveMemoryWarning 80 { 81 [super didReceiveMemoryWarning]; 82 83 //移除所有下載操作 84 [self.queue cancelAllOperations]; 85 [self.operationDict removeAllObjects]; 86 //移除所有圖片緩存 87 [self.imageDict removeAllObjects]; 88 } 89 90 91 #pragma mark - Table view data source 92 93 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 94 95 return 1; 96 } 97 98 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 99 100 return self.appsArray.count; 101 } 102 103 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 104 static NSString *cellID = @"cellID"; 105 106 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; 107 108 if (!cell) { 109 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID]; 110 } 111 //取出模型 112 BWApp *app = [self.appsArray objectAtIndex:indexPath.row]; 113 114 cell.textLabel.text = app.name; 115 cell.detailTextLabel.text = app.download; 116 117 //先從imageDict緩存中取出圖片url對(duì)應(yīng)的image 118 UIImage *image = self.imageDict[app.icon]; 119 120 if (image) { //說明圖片已經(jīng)下載成功過 121 cell.imageView.image = image; 122 } 123 else //說明圖片未下載(沒有緩存) 124 { 125 //獲取caches路徑,拼接文件路徑 126 NSString *filePath = appImageCachesPath(app.icon); 127 128 NSData *data = [NSData dataWithContentsOfFile:filePath]; 129 130 if (data) { //沙盒中存在這個(gè)圖片 131 cell.imageView.image = [UIImage imageWithData:data]; 132 } 133 else{ 134 //顯示占位圖片 135 cell.imageView.image = [UIImage imageNamed:@"placeholder"]; 136 } 137 138 [self download:app.icon andIndexPath:indexPath]; 139 } 140 return cell; 141 } 142 143 - (void)download:(NSString *)imageUrl andIndexPath:(NSIndexPath *)indexPath 144 { 145 //取出當(dāng)前圖片對(duì)應(yīng)的下載操作(operation對(duì)象) 146 NSBlockOperation *operation = self.operationDict[imageUrl]; 147 148 if (operation) return; 149 150 // __weak BWTableViewController *vc = self; 151 __weak typeof(self) appVC = self; 152 153 //創(chuàng)建操作,下載圖片 154 operation = [NSBlockOperation blockOperationWithBlock:^{ 155 NSURL *url = [NSURL URLWithString:imageUrl]; 156 NSData *data = [NSData dataWithContentsOfURL:url]; 157 UIImage *image = [UIImage imageWithData:data]; 158 159 //回到主線程 160 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 161 162 //判斷圖片是否存在 163 if (image) { 164 //存放圖片到字典中 165 appVC.imageDict[imageUrl] = image; 166 #warning 沙盒緩存 167 //將圖片存入沙盒之中 UIImage --> NSData --> File(文件) 168 NSData *data = UIImagePNGRepresentation(image); 169 170 // //獲取caches路徑 171 // NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 172 // 173 // //拼接文件路徑 174 // NSString *fileName = [imageUrl lastPathComponent]; 175 // NSString *filePath = [cachesPath stringByAppendingPathComponent:fileName]; 176 177 //寫入緩存 178 [data writeToFile:appImageCachesPath(imageUrl) atomically:YES]; 179 180 //UIImageJPEGRepresentation(UIImage * _Nonnull image, CGFloat compressionQuality) 181 } 182 //從字典中移除下載操作 183 [appVC.operationDict removeObjectForKey:imageUrl]; 184 //刷新表格 185 //[self.tableView reloadData]; 186 [appVC.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; 187 }]; 188 }]; 189 //添加操作到隊(duì)列中 190 [appVC.queue addOperation:operation]; 191 //添加操作到字典中(為了解決重復(fù)下載) 192 appVC.operationDict[imageUrl] = operation; 193 } 194 //保證圖片只下載過一次 195 //當(dāng)用戶開始拖拽表格時(shí) 196 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 197 { 198 //暫停下載 199 [self.queue setSuspended:YES]; 200 } 201 //用戶停止拖拽表格時(shí) 202 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 203 { 204 //恢復(fù)下載 205 [self.queue setSuspended:NO]; 206 } 207 208 209 @end三、自定義NSOperation
1 // 2 // BWApp.h 3 // IOS_0120_NSOperation防止重復(fù)下載 4 // 5 // Created by ma c on 16/1/20. 6 // Copyright ? 2016年 博文科技. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface BWApp : NSObject 12 13 @property (nonatomic, copy) NSString *name; 14 @property (nonatomic, copy) NSString *download; 15 @property (nonatomic, copy) NSString *icon; 16 17 + (instancetype)appWithDict:(NSDictionary *)dict; 18 19 @end 20 21 22 // 23 // BWApp.m 24 // IOS_0120_NSOperation防止重復(fù)下載 25 // 26 // Created by ma c on 16/1/20. 27 // Copyright ? 2016年 博文科技. All rights reserved. 28 // 29 30 #import "BWApp.h" 31 32 @implementation BWApp 33 34 + (instancetype)appWithDict:(NSDictionary *)dict 35 { 36 BWApp *app = [[self alloc] init]; 37 [app setValuesForKeysWithDictionary:dict]; 38 return app; 39 } 40 41 @end 1 // 2 // BWDownloadOperation.h 3 // IOS_0120_NSOperation防止重復(fù)下載 4 // 5 // Created by ma c on 16/1/21. 6 // Copyright ? 2016年 博文科技. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import <UIKit/UIKit.h> 11 12 @class BWDownloadOperation; 13 14 @protocol BWDownloadOperationDelegate <NSObject> 15 16 @optional 17 - (void)downloadOperation:(BWDownloadOperation *)operation didFinishDownload:(UIImage *)image; 18 19 @end 20 21 @interface BWDownloadOperation : NSOperation 22 23 @property (nonatomic, copy) NSString *imageUrl; 24 @property (nonatomic, strong) NSIndexPath *indexPath; 25 26 @property (nonatomic, weak) id<BWDownloadOperationDelegate> delegate; 27 28 29 @end 30 31 32 // 33 // BWDownloadOperation.m 34 // IOS_0120_NSOperation防止重復(fù)下載 35 // 36 // Created by ma c on 16/1/21. 37 // Copyright ? 2016年 博文科技. All rights reserved. 38 // 39 40 #import "BWDownloadOperation.h" 41 42 @implementation BWDownloadOperation 43 44 - (void)main 45 { 46 @autoreleasepool { 47 48 if (self.isCancelled) return; 49 50 //創(chuàng)建操作,下載圖片 51 NSURL *url = [NSURL URLWithString:self.imageUrl]; 52 NSData *data = [NSData dataWithContentsOfURL:url]; 53 UIImage *image = [UIImage imageWithData:data]; 54 55 if (self.isCancelled) return; 56 57 //回到主線程 58 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 59 if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:)]) { 60 [self.delegate downloadOperation:self didFinishDownload:image]; 61 } 62 }]; 63 } 64 } 65 @end?
1 // 2 // BWTableViewController.m 3 // IOS_0120_NSOperation防止重復(fù)下載 4 // 5 // Created by ma c on 16/1/20. 6 // Copyright ? 2016年 博文科技. All rights reserved. 7 // 8 9 #import "BWTableViewController.h" 10 #import "BWApp.h" 11 #import "BWDownloadOperation.h" 12 13 #define appImageCachesPath(url) [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[url lastPathComponent]] 14 15 @interface BWTableViewController ()<BWDownloadOperationDelegate> 16 17 //所有應(yīng)用數(shù)據(jù) 18 @property (nonatomic, strong) NSMutableArray *appsArray; 19 //存放所有下載操作的隊(duì)列 20 @property (nonatomic, strong) NSOperationQueue *queue; 21 //存放所有下載操作(url是key,operation對(duì)象是value) 22 @property (nonatomic, strong) NSMutableDictionary *operationDict; 23 //緩存圖片 24 @property (nonatomic, strong) NSMutableDictionary *imageDict; 25 26 @end 27 28 @implementation BWTableViewController 29 30 #pragma mark - 懶加載 31 - (NSMutableArray *)appsArray 32 { 33 if (!_appsArray) { 34 NSMutableArray *appArr = [[NSMutableArray alloc] init]; 35 36 NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"]; 37 38 NSArray *dictArr = [NSArray arrayWithContentsOfFile:path]; 39 40 for (NSDictionary *dict in dictArr) { 41 42 BWApp *app = [BWApp appWithDict:dict]; 43 [appArr addObject:app]; 44 } 45 _appsArray = appArr; 46 } 47 return _appsArray; 48 } 49 50 - (NSOperationQueue *)queue 51 { 52 if (!_queue) { 53 _queue = [[NSOperationQueue alloc] init]; 54 } 55 return _queue; 56 } 57 58 - (NSMutableDictionary *)operationDict 59 { 60 if (!_operationDict) { 61 _operationDict = [[NSMutableDictionary alloc] init]; 62 } 63 return _operationDict; 64 } 65 66 - (NSMutableDictionary *)imageDict 67 { 68 if (!_imageDict) { 69 _imageDict = [[NSMutableDictionary alloc] init]; 70 } 71 return _imageDict; 72 } 73 74 #pragma mark - 初始化 75 - (void)viewDidLoad { 76 [super viewDidLoad]; 77 78 } 79 80 - (void)didReceiveMemoryWarning 81 { 82 [super didReceiveMemoryWarning]; 83 84 //移除所有下載操作 85 [self.queue cancelAllOperations]; 86 [self.operationDict removeAllObjects]; 87 //移除所有圖片緩存 88 [self.imageDict removeAllObjects]; 89 } 90 91 92 #pragma mark - Table view data source 93 94 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 95 96 return 1; 97 } 98 99 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 100 101 return self.appsArray.count; 102 } 103 104 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 105 static NSString *cellID = @"cellID"; 106 107 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; 108 109 if (!cell) { 110 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID]; 111 } 112 //取出模型 113 BWApp *app = [self.appsArray objectAtIndex:indexPath.row]; 114 115 cell.textLabel.text = app.name; 116 cell.detailTextLabel.text = app.download; 117 118 //先從imageDict緩存中取出圖片url對(duì)應(yīng)的image 119 UIImage *image = self.imageDict[app.icon]; 120 121 if (image) { //說明圖片已經(jīng)下載成功過 122 cell.imageView.image = image; 123 } 124 else //說明圖片未下載(沒有緩存) 125 { 126 //獲取caches路徑,拼接文件路徑 127 NSString *filePath = appImageCachesPath(app.icon); 128 129 NSData *data = [NSData dataWithContentsOfFile:filePath]; 130 131 if (data) { //沙盒中存在這個(gè)圖片 132 cell.imageView.image = [UIImage imageWithData:data]; 133 } 134 else{ 135 //顯示占位圖片 136 cell.imageView.image = [UIImage imageNamed:@"placeholder"]; 137 } 138 139 [self download:app.icon andIndexPath:indexPath]; 140 } 141 return cell; 142 } 143 144 - (void)download:(NSString *)imageUrl andIndexPath:(NSIndexPath *)indexPath 145 { 146 //取出當(dāng)前圖片對(duì)應(yīng)的下載操作(operation對(duì)象) 147 BWDownloadOperation *operation = self.operationDict[imageUrl]; 148 149 if (operation) return; 150 151 //創(chuàng)建操作下載圖片 152 operation = [[BWDownloadOperation alloc] init]; 153 operation.imageUrl = imageUrl; 154 operation.indexPath = indexPath; 155 156 //設(shè)置代理 157 operation.delegate = self; 158 159 //添加操作到隊(duì)列中 160 [self.queue addOperation:operation]; 161 162 //添加操作到字典中(為了解決重復(fù)下載) 163 self.operationDict[imageUrl] = operation; 164 165 } 166 167 #pragma mark - 下載代理方法 168 169 - (void)downloadOperation:(BWDownloadOperation *)operation didFinishDownload:(UIImage *)image 170 { 171 172 173 //UIImageJPEGRepresentation(<#UIImage * _Nonnull image#>, <#CGFloat compressionQuality#>) 174 175 //判斷圖片是否存在 176 if (image) { 177 //存放圖片到字典中 178 self.imageDict[operation.imageUrl] = image; 179 180 #warning 沙盒緩存 181 //將圖片存入沙盒之中 UIImage --> NSData --> File(文件) 182 NSData *data = UIImagePNGRepresentation(image); 183 184 //寫入緩存 185 [data writeToFile:appImageCachesPath(operation.imageUrl) atomically:YES]; 186 187 } 188 //從字典中移除下載操作(防止operationDict的下載操作越來越大,保證下載失敗后能重新下載) 189 [self.operationDict removeObjectForKey:operation.imageUrl]; 190 //刷新表格 191 //[self.tableView reloadData]; 192 [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone]; 193 } 194 195 196 //保證圖片只下載過一次 197 //當(dāng)用戶開始拖拽表格時(shí) 198 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 199 { 200 //暫停下載 201 [self.queue setSuspended:YES]; 202 } 203 //用戶停止拖拽表格時(shí) 204 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 205 { 206 //恢復(fù)下載 207 [self.queue setSuspended:NO]; 208 } 209 210 211 @end?
?
四、SDWebImage
1 // 2 // BWApp.h 3 // IOS_0120_NSOperation防止重復(fù)下載 4 // 5 // Created by ma c on 16/1/20. 6 // Copyright ? 2016年 博文科技. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface BWApp : NSObject 12 13 @property (nonatomic, copy) NSString *name; 14 @property (nonatomic, copy) NSString *download; 15 @property (nonatomic, copy) NSString *icon; 16 17 + (instancetype)appWithDict:(NSDictionary *)dict; 18 19 @end 20 21 22 // 23 // BWApp.m 24 // IOS_0120_NSOperation防止重復(fù)下載 25 // 26 // Created by ma c on 16/1/20. 27 // Copyright ? 2016年 博文科技. All rights reserved. 28 // 29 30 #import "BWApp.h" 31 32 @implementation BWApp 33 34 + (instancetype)appWithDict:(NSDictionary *)dict 35 { 36 BWApp *app = [[self alloc] init]; 37 [app setValuesForKeysWithDictionary:dict]; 38 return app; 39 } 40 41 @end 1 // 2 // BWTableViewController.m 3 // IOS_0120_NSOperation防止重復(fù)下載 4 // 5 // Created by ma c on 16/1/20. 6 // Copyright ? 2016年 博文科技. All rights reserved. 7 // 8 9 #import "BWTableViewController.h" 10 #import "BWApp.h" 11 #import "UIImageView+WebCache.h" 12 13 @interface BWTableViewController () 14 15 //所有應(yīng)用數(shù)據(jù) 16 @property (nonatomic, strong) NSMutableArray *appsArray; 17 18 @end 19 20 @implementation BWTableViewController 21 22 #pragma mark - 懶加載 23 - (NSMutableArray *)appsArray 24 { 25 if (!_appsArray) { 26 NSMutableArray *appArr = [[NSMutableArray alloc] init]; 27 28 NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"]; 29 30 NSArray *dictArr = [NSArray arrayWithContentsOfFile:path]; 31 32 for (NSDictionary *dict in dictArr) { 33 34 BWApp *app = [BWApp appWithDict:dict]; 35 [appArr addObject:app]; 36 } 37 _appsArray = appArr; 38 } 39 return _appsArray; 40 } 41 42 #pragma mark - 初始化 43 - (void)viewDidLoad { 44 [super viewDidLoad]; 45 46 } 47 48 - (void)didReceiveMemoryWarning 49 { 50 [super didReceiveMemoryWarning]; 51 } 52 53 #pragma mark - Table view data source 54 55 //- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 56 // 57 // return 1; 58 //} 59 60 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 61 62 // return self.appsArray.count; 63 return 1; 64 } 65 66 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 67 68 static NSString *cellID = @"cellID"; 69 70 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; 71 72 if (!cell) { 73 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID]; 74 } 75 //取出模型 76 BWApp *app = [self.appsArray objectAtIndex:indexPath.row]; 77 //設(shè)置基本信息 78 cell.textLabel.text = app.name; 79 cell.detailTextLabel.text = app.download; 80 81 //下載圖片 82 // NSURL *url = [NSURL URLWithString:@"http://img.cnblogs.com/ad/not-to-stop-questioning.jpg"]; 83 84 NSURL *url = [NSURL URLWithString:app.icon]; 85 UIImage *image = [UIImage imageNamed:@"placeholder"]; 86 // [cell.imageView sd_setImageWithURL:url placeholderImage:image]; 87 88 SDWebImageOptions options = SDWebImageRetryFailed | SDWebImageLowPriority; 89 90 [cell.imageView sd_setImageWithURL:url placeholderImage:image options:options progress:^(NSInteger receivedSize, NSInteger expectedSize) { 91 92 NSLog(@"下載進(jìn)度:%f",(double)receivedSize / expectedSize); 93 94 } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { 95 NSLog(@"-----圖片加載完畢-----%@",image); 96 }]; 97 98 return cell; 99 } 100 101 @end 1 - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application 2 { 3 SDWebImageManager *maneger = [SDWebImageManager sharedManager]; 4 //1.取消正在下載的操作 5 [maneger cancelAll]; 6 //2.清除內(nèi)存緩存 7 [maneger.imageCache clearMemory]; 8 maneger.imageCache.maxCacheAge = 100*24*60*60; 9 }?
轉(zhuǎn)載于:https://www.cnblogs.com/oc-bowen/p/5144991.html
總結(jié)
以上是生活随笔為你收集整理的IOS-多线程(NSOperation)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GIS基本概念
- 下一篇: SDL2源码分析6:拷贝到渲染器(SDL