手机
当前位置:查字典教程网 >编程开发 >IOS开发 >iOS多线程应用开发中自定义NSOperation类的实例解析
iOS多线程应用开发中自定义NSOperation类的实例解析
摘要:一、实现一个简单的tableView显示效果实现效果展示:代码示例(使用以前在主控制器中进行业务处理的方式)1.新建一个项目,让控制器继承自...

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

实现效果展示:

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

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

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类的实例解析2

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

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

新建一个类,继承自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类的实例解析4

二、自定义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类的实例解析5

【iOS多线程应用开发中自定义NSOperation类的实例解析】相关文章:

在IOS中为什么使用多线程及多线程实现的三种方法

IOS开发笔记整理49之详解定位CLLocation

iOS远程推送Push开发教程

详解iOS应用中自定义UIBarButtonItem导航按钮的创建方法

iOS开发:自定义状态栏代码详解

IOS开发:提示框的正确实现方式

iOS10添加本地推送(Local Notification)实例

iOS多线程应用开发中使用NSOperation类的基本方法

理解iOS多线程应用的开发以及线程的创建方法

iOS App开发中Objective-C使用正则表达式进行匹配的方法

精品推荐
分类导航