源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

iOS多线程应用开发中自定义NSOperation类的实例解析

  • 时间:2022-08-24 00:11 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:iOS多线程应用开发中自定义NSOperation类的实例解析
[b]一、实现一个简单的tableView显示效果[/b] 实现效果展示: [img]http://files.jb51.net/file_images/article/201601/20161393952592.png?20160394011[/img] 代码示例(使用以前在主控制器中进行业务处理的方式) 1.新建一个项目,让控制器继承自UITableViewController。
[u]复制代码[/u] 代码如下:
// //  YYViewController.h //  01-自定义Operation // //  Created by apple on 14-6-26. //  Copyright (c) 2014年 itcase. All rights reserved. // #import <UIKit/UIKit.h> @interface YYViewController : UITableViewController @end
2.处理storyboard中得界面,如下: [img]http://files.jb51.net/file_images/article/201601/20161394021020.png?20160394029[/img] 3.根据plist文件,字典转模型 [img]http://files.jb51.net/file_images/article/201601/20161394039602.png?20160394047[/img] 新建一个类,继承自NSObject,作为数据的模型 YYappModel.h文件
[u]复制代码[/u] 代码如下:
// //  YYappModel.h //  01-自定义Operation // //  Created by apple on 14-6-26. //  Copyright (c) 2014年 itcase. All rights reserved. // #import <Foundation/Foundation.h> @interface YYappModel : NSObject /**  *应用名称  */ @property(nonatomic,copy)NSString *name; /**  *  应用图片  */ @property(nonatomic,copy)NSString *icon; /**  *  应用的下载量  */ @property(nonatomic,copy)NSString *download; +(instancetype)appModelWithDict:(NSDictionary *)dict; -(instancetype)initWithDict:(NSDictionary *)dict; @end
YYappModel.m文件
[u]复制代码[/u] 代码如下:
// //  YYappModel.m //  01-自定义Operation // //  Created by apple on 14-6-26. //  Copyright (c) 2014年 itcase. All rights reserved. // #import "YYappModel.h" @implementation YYappModel -(instancetype)initWithDict:(NSDictionary *)dict {     if (self=[super init]) {         [self setValuesForKeysWithDictionary:dict];     }     return self; } //工厂方法 +(instancetype)appModelWithDict:(NSDictionary *)dict {     return [[self alloc]initWithDict:dict]; } @end
主控制器中得逻辑控制部分,YYViewController.m文件
[u]复制代码[/u] 代码如下:
// //  YYViewController.m //  01-自定义Operation // //  Created by apple on 14-6-26. //  Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" #import "YYappModel.h" @interface YYViewController () @property(nonatomic,strong)NSArray *apps; @end
[u]复制代码[/u] 代码如下:
@implementation YYViewController #pragma mark- 懒加载 -(NSArray *)apps {     if (_apps==nil) {         NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];         NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];                 //字典转模型         NSMutableArray *array=[NSMutableArray array];         for (NSDictionary *dict in tempArray) {             YYappModel *app=[YYappModel appModelWithDict:dict];             [array addObject:app];         }         _apps=array;     }     return _apps; } #pragma mark-数据源方法 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return self.apps.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {     static NSString *ID=@"ID";     UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];     if (cell==nil) {         cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];     }     YYappModel *app=self.apps[indexPath.row];     cell.textLabel.text=app.name;     cell.detailTextLabel.text=app.download;         //下载图片数据     NSLog(@"加载图片数据---%@", [NSThread currentThread]);     NSURL *url=[NSURL URLWithString:app.icon];     NSData *data=[NSData dataWithContentsOfURL:url];     UIImage *imgae=[UIImage imageWithData:data];     cell.imageView.image=imgae;     NSLog(@"完成显示");     return cell; } @end
打印查看: [img]http://files.jb51.net/file_images/article/201601/20161394102297.png?20160394110[/img] [b]二、自定义NSOperation[/b] 说明:上面的下载图片数据部分是一个非常耗时的操作,这个操作任务在主线程完成,会严重的影响到用户体验,造成UI卡的现象。下面通过自定义NSOperation,新开线程,让加载图片的任务异步执行。 1.通过代理 在上面的基础上,新建一个类,让其继承自NSOperation。 YYdownLoadOperation.h文件
[u]复制代码[/u] 代码如下:
// //  YYdownLoadOperation.h //  01-自定义Operation // //  Created by apple on 14-6-26. //  Copyright (c) 2014年 itcase. All rights reserved. // #import <Foundation/Foundation.h> #pragma mark-设置代理和代理方法 @class YYdownLoadOperation; @protocol YYdownLoadOperationDelegate <NSObject> -(void)downLoadOperation:(YYdownLoadOperation*)operation didFishedDownLoad:(UIImage *)image; @end
[u]复制代码[/u] 代码如下:
@interface YYdownLoadOperation : NSOperation @property(nonatomic,copy)NSString *url; @property(nonatomic,strong)NSIndexPath *indexPath; @property(nonatomic,strong)id <YYdownLoadOperationDelegate> delegate; @end
YYdownLoadOperation.m文件
[u]复制代码[/u] 代码如下:
// //  YYdownLoadOperation.m //  01-自定义Operation // //  Created by apple on 14-6-26. //  Copyright (c) 2014年 itcase. All rights reserved. // #import "YYdownLoadOperation.h" @implementation YYdownLoadOperation -(void)main {     NSURL *url=[NSURL URLWithString:self.url];     NSData *data=[NSData dataWithContentsOfURL:url];     UIImage *imgae=[UIImage imageWithData:data];         NSLog(@"--%@--",[NSThread currentThread]);     //图片下载完毕后,通知代理     if ([self.delegate respondsToSelector:@selector(downLoadOperation:didFishedDownLoad:)]) {         dispatch_async(dispatch_get_main_queue(), ^{//回到主线程,传递数据给代理对象              [self.delegate downLoadOperation:self didFishedDownLoad:imgae];         });     } } @end
主控制器中的业务逻辑:
[u]复制代码[/u] 代码如下:
// //  YYViewController.m //  01-自定义Operation // //  Created by apple on 14-6-26. //  Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" #import "YYappModel.h" #import "YYdownLoadOperation.h" @interface YYViewController ()<YYdownLoadOperationDelegate> @property(nonatomic,strong)NSArray *apps; @property(nonatomic,strong)NSOperationQueue *queue; @end
[u]复制代码[/u] 代码如下:
@implementation YYViewController #pragma mark- 懒加载apps -(NSArray *)apps {     if (_apps==nil) {         NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];         NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];                 //字典转模型         NSMutableArray *array=[NSMutableArray array];         for (NSDictionary *dict in tempArray) {             YYappModel *app=[YYappModel appModelWithDict:dict];             [array addObject:app];         }         _apps=array;     }     return _apps; } #pragma mark-懒加载queue -(NSOperationQueue *)queue {     if (_queue==Nil) {         _queue=[[NSOperationQueue alloc]init];         //设置最大并发数为3         _queue.maxConcurrentOperationCount=3;     }     return _queue; } #pragma mark-数据源方法 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return self.apps.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {     static NSString *ID=@"ID";     UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];     if (cell==nil) {         cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];     }     YYappModel *app=self.apps[indexPath.row];     cell.textLabel.text=app.name;     cell.detailTextLabel.text=app.download;          //下载图片数据 //    NSLog(@"加载图片数据---%@", [NSThread currentThread]); //    NSURL *url=[NSURL URLWithString:app.icon]; //    NSData *data=[NSData dataWithContentsOfURL:url]; //    UIImage *imgae=[UIImage imageWithData:data]; //    cell.imageView.image=imgae;         //创建一个OPeration对象     YYdownLoadOperation *operation=[[YYdownLoadOperation alloc]init];     operation.url=app.icon;     operation.indexPath=indexPath;     operation.delegate=self;         //把操作对象添加到队列中在去     [self.queue addOperation:operation]; //    NSLog(@"完成显示");     return cell; } -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image {     //返回图片数据给每行对应的cell的imageview.image     //取出tableview中indexPath这一行对应的cell     UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:operation.indexPath];     //显示图片     cell.imageView.image=image; //    NSLog(@"cell--index--%@---%@",operation.indexPath,[NSThread currentThread]);     //一定要刷新表格     [self.tableView reloadData];     NSLog(@"--%@--",[NSThread currentThread]); } @end
说明:通过打印可以发现上面的代码存在很大的问题。 问题1:需要保证一个url对应一个operation对象。 问题2:下载完需要移除。移除执行完毕的操作。 问题3:保证一个url对应一个image。 下面对主控制器中得代码进行改进:
[u]复制代码[/u] 代码如下:
// //  YYViewController.m //  01-自定义Operation // //  Created by apple on 14-6-26. //  Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" #import "YYappModel.h" #import "YYdownLoadOperation.h" @interface YYViewController ()<YYdownLoadOperationDelegate> @property(nonatomic,strong)NSArray *apps; @property(nonatomic,strong)NSOperationQueue *queue; @property(nonatomic,strong)NSMutableDictionary *operations; @property(nonatomic,strong)NSMutableDictionary *images; @end
[u]复制代码[/u] 代码如下:
@implementation YYViewController #pragma mark- 懒加载apps -(NSArray *)apps {     if (_apps==nil) {         NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];         NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];                 //字典转模型         NSMutableArray *array=[NSMutableArray array];         for (NSDictionary *dict in tempArray) {             YYappModel *app=[YYappModel appModelWithDict:dict];             [array addObject:app];         }         _apps=array;     }     return _apps; } #pragma mark-懒加载queue -(NSOperationQueue *)queue {     if (_queue==Nil) {         _queue=[[NSOperationQueue alloc]init];         //设置最大并发数为3         _queue.maxConcurrentOperationCount=3;     }     return _queue; } #pragma mark-懒加载operations -(NSMutableDictionary *)operations {     if (_operations==Nil) {         _operations=[NSMutableDictionary dictionary];     }     return _operations; } #pragma mark-懒加载images -(NSMutableDictionary *)images {     if (_images==Nil) {         _images=[NSMutableDictionary dictionary];     }     return _images; } #pragma mark-数据源方法 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return self.apps.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {     static NSString *ID=@"ID";     UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];     if (cell==nil) {         cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];     }     YYappModel *app=self.apps[indexPath.row];     cell.textLabel.text=app.name;     cell.detailTextLabel.text=app.download;         //保证一个url对应一个image对象     UIImage *image=self.images[app.icon];     if (image) {//缓存中有图片         cell.imageView.image=image;     }else       //  缓存中没有图片,得下载     {         //先设置一张占位图片         cell.imageView.image=[UIImage imageNamed:@"57437179_42489b0"];         YYdownLoadOperation *operation=self.operations[app.icon];         if (operation) {//正在下载             //什么都不做         }else  //当前没有下载,那就创建操作         {             operation=[[YYdownLoadOperation alloc]init];             operation.url=app.icon;             operation.indexPath=indexPath;             operation.delegate=self;             [self.queue addOperation:operation];//异步下载             self.operations[app.icon]=operation;         }     }         return cell; } -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image {     //1.移除执行完毕的操作     [self.operations removeObjectForKey:operation.url];         //2.将图片放到缓存中     self.images[operation.url]=image;     //3.刷新表格(只刷新下载的那一行)          [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];     NSLog(@"--%d--%@--",operation.indexPath.row,[NSThread currentThread]); } @end
打印查看: [img]http://files.jb51.net/file_images/article/201601/20161394130477.png?20160394137[/img]
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部