您的位置:首页 > 移动开发 > IOS开发

IOS多线程之NSOperation(自定义)

2015-02-26 16:03 323 查看
转载自:http://www.cnblogs.com/wendingding/p/3811121.html ;

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

实现效果展示:



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

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

1 //

2 // YYViewController.h

3 // 01-自定义Operation

4 //

5 // Created by apple on 14-6-26.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import <UIKit/UIKit.h>

10

11 @interface YYViewController : UITableViewController

12

13 @end

2.处理storyboard中得界面,如下:



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



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

YYappModel.h文件

1 //

2 // YYappModel.h

3 // 01-自定义Operation

4 //

5 // Created by apple on 14-6-26.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import <Foundation/Foundation.h>

10

11 @interface YYappModel : NSObject

12 /**

13 *应用名称

14 */

15 @property(nonatomic,copy)NSString *name;

16 /**

17 * 应用图片

18 */

19 @property(nonatomic,copy)NSString *icon;

20 /**

21 * 应用的下载量

22 */

23 @property(nonatomic,copy)NSString *download;

24

25 +(instancetype)appModelWithDict:(NSDictionary *)dict;

26 -(instancetype)initWithDict:(NSDictionary *)dict;

27 @end

YYappModel.m文件

1 //

2 // YYappModel.m

3 // 01-自定义Operation

4 //

5 // Created by apple on 14-6-26.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import "YYappModel.h"

10

11 @implementation YYappModel

12

13 -(instancetype)initWithDict:(NSDictionary *)dict

14 {

15 if (self=[super init]) {

16 [self setValuesForKeysWithDictionary:dict];

17 }

18 return self;

19 }

20

21 //工厂方法

22 +(instancetype)appModelWithDict:(NSDictionary *)dict

23 {

24 return [[self alloc]initWithDict:dict];

25 }

26 @end

主控制器中得逻辑控制部分,YYViewController.m文件

1 //

2 // YYViewController.m

3 // 01-自定义Operation

4 //

5 // Created by apple on 14-6-26.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import "YYViewController.h"

10 #import "YYappModel.h"

11

12 @interface YYViewController ()

13 @property(nonatomic,strong)NSArray *apps;

14

15 @end

16

17 @implementation YYViewController

18 #pragma mark-
懒加载

19 -(NSArray *)apps

20 {

21 if (_apps==nil)
{

22 NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];

23 NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];

24

25 //字典转模型

26 NSMutableArray *array=[NSMutableArray array];

27 for (NSDictionary
*dict in tempArray) {

28 YYappModel *app=[YYappModel appModelWithDict:dict];

29 [array addObject:app];

30 }

31 _apps=array;

32 }

33 return _apps;

34 }

35

36 #pragma mark-数据源方法

37 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

38 {

39 return self.apps.count;

40 }

41

42 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

43 {

44 static NSString
*ID=@"ID";

45 UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];

46 if (cell==nil)
{

47 cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:ID];

48 }

49 YYappModel *app=self.apps[indexPath.row];

50 cell.textLabel.text=app.name;

51 cell.detailTextLabel.text=app.download;

52

53 //下载图片数据

54 NSLog(@"加载图片数据---%@",
[NSThread currentThread]);

55 NSURL *url=[NSURL URLWithString:app.icon];

56 NSData *data=[NSData dataWithContentsOfURL:url];

57 UIImage *imgae=[UIImage imageWithData:data];

58 cell.imageView.image=imgae;

59 NSLog(@"完成显示");

60 return cell;

61 }

62

63 @end

打印查看:



二、自定义NSOperation

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

1.通过代理

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

YYdownLoadOperation.h文件

1 //

2 // YYdownLoadOperation.h

3 // 01-自定义Operation

4 //

5 // Created by apple on 14-6-26.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import <Foundation/Foundation.h>

10

11 #pragma mark-设置代理和代理方法

12 @class YYdownLoadOperation;

13 @protocol YYdownLoadOperationDelegate <NSObject>

14 -(void)downLoadOperation:(YYdownLoadOperation*)operation didFishedDownLoad:(UIImage *)image;

15 @end

16

17 @interface YYdownLoadOperation : NSOperation

18 @property(nonatomic,copy)NSString *url;

19 @property(nonatomic,strong)NSIndexPath *indexPath;

20 @property(nonatomic,strong)id <YYdownLoadOperationDelegate> delegate;

21 @end

YYdownLoadOperation.m文件

1 //

2 // YYdownLoadOperation.m

3 // 01-自定义Operation

4 //

5 // Created by apple on 14-6-26.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import "YYdownLoadOperation.h"

10

11 @implementation YYdownLoadOperation

12 -(void)main

13 {

14 NSURL *url=[NSURL URLWithString:self.url];

15 NSData *data=[NSData dataWithContentsOfURL:url];

16 UIImage *imgae=[UIImage imageWithData:data];

17

18 NSLog(@"--%@--",[NSThread
currentThread]);

19 //图片下载完毕后,通知代理

20 if ([self.delegate respondsToSelector:@selector(downLoadOperation:didFishedDownLoad:)])
{

21 dispatch_async(dispatch_get_main_queue(), ^{//回到主线程,传递数据给代理对象

22 [self.delegate downLoadOperation:self
didFishedDownLoad:imgae];

23 });

24 }

25 }

26 @end

主控制器中的业务逻辑:

1 //

2 // YYViewController.m

3 // 01-自定义Operation

4 //

5 // Created by apple on 14-6-26.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import "YYViewController.h"

10 #import "YYappModel.h"

11 #import "YYdownLoadOperation.h"

12

13 @interface YYViewController ()<YYdownLoadOperationDelegate>

14 @property(nonatomic,strong)NSArray *apps;

15 @property(nonatomic,strong)NSOperationQueue *queue;

16

17 @end

18

19 @implementation YYViewController

20 #pragma mark- 懒加载apps

21 -(NSArray *)apps

22 {

23 if (_apps==nil) {

24 NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];

25 NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];

26

27 //字典转模型

28 NSMutableArray *array=[NSMutableArray array];

29 for (NSDictionary *dict in tempArray)
{

30 YYappModel *app=[YYappModel appModelWithDict:dict];

31 [array addObject:app];

32 }

33 _apps=array;

34 }

35 return _apps;

36 }

37

38 #pragma mark-懒加载queue

39 -(NSOperationQueue *)queue

40 {

41 if (_queue==Nil) {

42 _queue=[[NSOperationQueue alloc]init];

43 //设置最大并发数为3

44 _queue.maxConcurrentOperationCount=3;

45 }

46 return _queue;

47 }

48

49 #pragma mark-数据源方法

50 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

51 {

52 return self.apps.count;

53 }

54 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

55 {

56 static NSString *ID=@"ID";

57 UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];

58 if (cell==nil) {

59 cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];

60 }

61 YYappModel *app=self.apps[indexPath.row];

62 cell.textLabel.text=app.name;

63 cell.detailTextLabel.text=app.download;

64

65 //下载图片数据

66 // NSLog(@"加载图片数据---%@",
[NSThread currentThread]);

67 // NSURL *url=[NSURL
URLWithString:app.icon];

68 // NSData *data=[NSData
dataWithContentsOfURL:url];

69 // UIImage
*imgae=[UIImage imageWithData:data];

70 // cell.imageView.image=imgae;

71

72 //创建一个OPeration对象

73 YYdownLoadOperation *operation=[[YYdownLoadOperation alloc]init];

74 operation.url=app.icon;

75 operation.indexPath=indexPath;

76 operation.delegate=self;

77

78 //把操作对象添加到队列中在去

79 [self.queue addOperation:operation];

80

81 // NSLog(@"完成显示");

82 return cell;

83 }

84 -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage
*)image

85 {

86 //返回图片数据给每行对应的cell的imageview.image

87 //取出tableview中indexPath这一行对应的cell

88 UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:operation.indexPath];

89 //显示图片

90 cell.imageView.image=image;

91 // NSLog(@"cell--index--%@---%@",operation.indexPath,[NSThread
currentThread]);

92 //一定要刷新表格

93 [self.tableView reloadData];

94 NSLog(@"--%@--",[NSThread
currentThread]);

95

96 }

97 @end

说明:通过打印可以发现上面的代码存在很大的问题。

问题1:需要保证一个url对应一个operation对象。

问题2:下载完需要移除。移除执行完毕的操作。

问题3:保证一个url对应一个image。

下面对主控制器中得代码进行改进:

1 //

2 // YYViewController.m

3 // 01-自定义Operation

4 //

5 // Created by apple on 14-6-26.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import "YYViewController.h"

10 #import "YYappModel.h"

11 #import "YYdownLoadOperation.h"

12

13 @interface YYViewController ()<YYdownLoadOperationDelegate>

14 @property(nonatomic,strong)NSArray *apps;

15 @property(nonatomic,strong)NSOperationQueue *queue;

16 @property(nonatomic,strong)NSMutableDictionary *operations;

17 @property(nonatomic,strong)NSMutableDictionary *images;

18

19 @end

20

21 @implementation YYViewController

22 #pragma mark- 懒加载apps

23 -(NSArray *)apps

24 {

25 if (_apps==nil) {

26 NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];

27 NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];

28

29 //字典转模型

30 NSMutableArray *array=[NSMutableArray array];

31 for (NSDictionary *dict in tempArray) {

32 YYappModel *app=[YYappModel appModelWithDict:dict];

33 [array addObject:app];

34 }

35 _apps=array;

36 }

37 return _apps;

38 }

39

40 #pragma mark-懒加载queue

41 -(NSOperationQueue *)queue

42 {

43 if (_queue==Nil) {

44 _queue=[[NSOperationQueue alloc]init];

45 //设置最大并发数为3

46 _queue.maxConcurrentOperationCount=3;

47 }

48 return _queue;

49 }

50

51 #pragma mark-懒加载operations

52 -(NSMutableDictionary *)operations

53 {

54 if (_operations==Nil) {

55 _operations=[NSMutableDictionary dictionary];

56 }

57 return _operations;

58 }

59

60 #pragma mark-懒加载images

61 -(NSMutableDictionary *)images

62 {

63 if (_images==Nil) {

64 _images=[NSMutableDictionary dictionary];

65 }

66 return _images;

67 }

68

69 #pragma mark-数据源方法

70 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

71 {

72 return self.apps.count;

73 }

74 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

75 {

76 static NSString *ID=@"ID";

77 UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];

78 if (cell==nil) {

79 cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];

80 }

81 YYappModel *app=self.apps[indexPath.row];

82 cell.textLabel.text=app.name;

83 cell.detailTextLabel.text=app.download;

84

85 //保证一个url对应一个image对象

86 UIImage *image=self.images[app.icon];

87 if (image) {//缓存中有图片

88 cell.imageView.image=image;

89 }else // 缓存中没有图片,得下载

90 {

91 //先设置一张占位图片

92 cell.imageView.image=[UIImage imageNamed:@"57437179_42489b0"];

93 YYdownLoadOperation *operation=self.operations[app.icon];

94 if (operation) {//正在下载

95 //什么都不做

96 }else //当前没有下载,那就创建操作

97 {

98 operation=[[YYdownLoadOperation alloc]init];

99 operation.url=app.icon;

100 operation.indexPath=indexPath;

101 operation.delegate=self;

102 [self.queue addOperation:operation];//异步下载

103 self.operations[app.icon]=operation;

104 }

105 }

106

107

108 return cell;

109 }

110 -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage
*)image

111 {

112 //1.移除执行完毕的操作

113 [self.operations removeObjectForKey:operation.url];

114

115 //2.将图片放到缓存中

116 self.images[operation.url]=image;

117

118 //3.刷新表格(只刷新下载的那一行)

119

120[self.tableView reloadRowsAtIndexPaths:@[operation.indexPath]withRowAnimation:UITableViewRowAnimationAutomatic];

121 NSLog(@"--%d--%@--",operation.indexPath.row,[NSThread
currentThread]);122 123 }124 @end

打印查看:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios 多线程