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

2025-05-29 0 87

一、实现一个简单的tableview显示效果

实现效果展示:

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

代码示例(使用以前在主控制器中进行业务处理的方式)

1.新建一个项目,让控制器继承自uitableviewcontroller。

复制代码 代码如下:


//
// 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中得界面,如下:

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

3.根据plist文件,字典转模型

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

新建一个类,继承自nsobject,作为数据的模型

yyappmodel.h文件

复制代码 代码如下:


//
// 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文件

复制代码 代码如下:


//
// 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文件

复制代码 代码如下:


//
// 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

复制代码 代码如下:


@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


打印查看:

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

二、自定义nsoperation

说明:上面的下载图片数据部分是一个非常耗时的操作,这个操作任务在主线程完成,会严重的影响到用户体验,造成ui卡的现象。下面通过自定义nsoperation,新开线程,让加载图片的任务异步执行。

1.通过代理

在上面的基础上,新建一个类,让其继承自nsoperation。

yydownloadoperation.h文件

复制代码 代码如下:


//
// 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

复制代码 代码如下:


@interface yydownloadoperation : nsoperation
@property(nonatomic,copy)nsstring *url;
@property(nonatomic,strong)nsindexpath *indexpath;
@property(nonatomic,strong)id <yydownloadoperationdelegate> delegate;
@end


yydownloadoperation.m文件

复制代码 代码如下:


//
// 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


主控制器中的业务逻辑:

复制代码 代码如下:


//
// 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

复制代码 代码如下:


@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。
下面对主控制器中得代码进行改进:

复制代码 代码如下:


//
// 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

复制代码 代码如下:


@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


打印查看:

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

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 iOS多线程应用开发中自定义NSOperation类的实例解析 https://www.kuaiidc.com/93733.html

相关文章

发表评论
暂无评论