iOS开发 自定义并发NSOperation实战
2017-01-21 本文已影响125人
MrZhaoCn
前一章节已经介绍了如何自定义并发NSOperation,本节将其应用到具体实例,如果自定义并发NSOperation不会,请移步http://www.jianshu.com/p/65629ba90d6a
在ZCCurrentOperation.h文件中代码如下:
//
// ZCCurrentOperation.h
// 自定义非并发NSOPeration
//
// Created by MrZhao on 16/9/13.
// Copyright © 2016年 MrZhao. All rights reserved.
//
/*
*自定义并发的NSOperation需要以下步骤:
1.start方法:该方法必须实现,
2.main:该方法可选,如果你在start方法中定义了你的任务,则这个方法就可以不实现,但通常为了代码逻辑清晰,通常会在该方法中定义自己的任务
3.isExecuting isFinished 主要作用是在线程状态改变时,产生适当的KVO通知
4.isConcurrent :必须覆盖并返回YES;
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class ZCCurrentOperation;
@protocol currentOperationDelegate <NSObject>
-(void)downLoadOperation:(ZCCurrentOperation*)operation didFishedDownLoad:(UIImage *)image;
@end
@interface ZCCurrentOperation : NSOperation {
BOOL executing;
BOOL finished;
}
@property (nonatomic, copy)NSString *urlStr;
@property (nonatomic, strong)NSIndexPath *indexPath;
@property (nonatomic, weak)id<currentOperationDelegate>delegate;
@end
在ZCCurrentOperation.m文件中代码如下:
// ZCCurrentOperation.m
// 自定义非并发NSOPeration
// https://github.com/MrZhaoCn/iOS-NSOperation.git
// Created by MrZhao on 16/9/13.
// Copyright © 2016年 MrZhao. All rights reserved.
#import "ZCCurrentOperation.h"
@implementation ZCCurrentOperation
- (id)init {
if(self = [super init]) {
executing = NO;
finished = NO;
}
return self;
}
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isExecuting {
return executing;
}
- (BOOL)isFinished {
return finished;
}
- (void)start {
//第一步就要检测是否被取消了,如果取消了,要实现相应的KVO
if ([self isCancelled]) {
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
return;
}
//如果没被取消,开始执行任务
[self willChangeValueForKey:@"isExecuting"];
[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
executing = YES;
[self didChangeValueForKey:@"isExecuting"];
}
- (void)main {
@try {
@autoreleasepool {
//在这里定义自己的并发任务
NSLog(@"自定义并发操作NSOperation");
NSURL *url=[NSURL URLWithString:self.urlStr];
NSData *data=[NSData dataWithContentsOfURL:url];
UIImage *imgae=[UIImage imageWithData:data];
//图片下载完毕后,通知代理
if ([self.delegate respondsToSelector:@selector(downLoadOperation:didFishedDownLoad:)]) {
dispatch_async(dispatch_get_main_queue(), ^{//回到主线程,传递数据给代理对象
[self.delegate downLoadOperation:self didFishedDownLoad:imgae];
});
}
NSThread *thread = [NSThread currentThread];
NSLog(@"%@",thread);
//任务执行完成后要实现相应的KVO
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
}
@catch (NSException *exception) {
}
}
@end
控制器的代码如下:
// ViewController.m
// 自定义并发NSOperation
//
// Created by MrZhao on 16/9/13.
// Copyright © 2016年 MrZhao. All rights reserved.
//
#import "ViewController.h"
#import "ZCCurrentOperation.h"
#import "ZCNetWorkingTool.h"
#import "MJExtension.h"
#import "ZCLiveUser.h"
@interface ViewController () <UITableViewDataSource,UITableViewDelegate,currentOperationDelegate>
@property (nonatomic, strong)NSMutableArray *dataSource;
@property (nonatomic, strong)NSOperationQueue *myQueue;
@property (nonatomic, strong)UITableView *tableView;
@property (nonatomic, strong)NSMutableDictionary *operations;
@property (nonatomic, strong)NSMutableDictionary *images;
@end
@implementation ViewController
static int page = 1;
#pragma mark life cycle
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.tableView];
//发送网络请求获取数据
[self loadData];
}
- (void)viewDidLayoutSubviews {
self.tableView.frame = self.view.bounds;
}
#pragma mark tableViewDataSourece
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ID = @"CELL";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
if (self.dataSource.count >0) {
ZCLiveUser *liveUser = self.dataSource[indexPath.row];
//保证一个url对应一个image对象
UIImage *image = self.images[liveUser.photo];
if (image) {//缓存中有图片
cell.imageView.image = image;
}
else { // 缓存中没有图片,得下载
//先设置一张占位图片
cell.imageView.image = [UIImage imageNamed:@"reflesh1_60x55"];
ZCCurrentOperation *operation = self.operations[liveUser.photo];
if (operation) {//正在下载
//什么都不做
}else {
//当前没有下载,那就创建操作
operation = [[ZCCurrentOperation alloc]init];
operation.urlStr = liveUser.photo;
operation.indexPath = indexPath;
operation.delegate = self;
[self.myQueue addOperation:operation];//异步下载
self.operations[liveUser.photo] = operation;
}
}
}
return cell;
}
- (void)loadData {
NSString *url = [NSString stringWithFormat:@"http://live.9158.com/Room/GetNewRoomOnline?page=%ld",(unsigned long)page];
ZCNetWorkingTool *tool = [ZCNetWorkingTool shareNetWorking];
[tool GETWithURL:url parameters:nil sucess:^(id reponseBody) {
NSArray *array = reponseBody[@"data"][@"list"];
//将字典数组转成模型数组
NSArray *arrayM =[ZCLiveUser objectArrayWithKeyValuesArray:array];
if (arrayM.count>0) {
[self.dataSource addObjectsFromArray:arrayM];
[self.tableView reloadData];
}
} failure:^(NSError *error) {
NSLog(@"数据加载失败");
}];
}
- (void)downLoadOperation:(ZCCurrentOperation *)operation didFishedDownLoad:(UIImage *)image{
//1.移除执行完毕的操作
[self.operations removeObjectForKey:operation.urlStr];
//2.将图片放到缓存中
self.images[operation.urlStr]=image;
//3.刷新表格(只刷新下载的那一行)
[self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark懒加载相关
- (NSOperationQueue *)myQueue {
if (!_myQueue) {
self.myQueue = [[NSOperationQueue alloc] init];
self.myQueue.maxConcurrentOperationCount = 3;
}
return _myQueue;
}
- (UITableView *)tableView {
if (!_tableView) {
self.tableView = [[UITableView alloc] init];
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
return _tableView;
}
- (NSMutableArray *)dataSource {
if (_dataSource == nil) {
_dataSource = [NSMutableArray array];
}
return _dataSource;
}
- (NSMutableDictionary *)operations {
if (!_operations) {
self.operations = [NSMutableDictionary dictionary];
}
return _operations;
}
- (NSMutableDictionary *)images {
if (!_images) {
self.images = [NSMutableDictionary dictionary];
}
return _images;
}
@end
20160914145257159.png
以上就是自定义并发NSOperation的一个简单应用,功能类似于SDWebImage.
代码地址:https://github.com/MrZhaoCn/iOS-NSOperation.git