zoukankan      html  css  js  c++  java
  • iOS多线程与网络开发之NSOperation

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载。

    假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 

    我要捐赠: 点击捐赠

    Cocos2d-X源代码下载:点我传送

    游戏官方下载:http://dwz.cn/RwTjl

    游戏视频预览:http://dwz.cn/RzHHd

    游戏开发博客:http://dwz.cn/RzJzI

    游戏源代码传送http://dwz.cn/Nret1


    A.NSOperation的基本使用
    1.NSOperation的作用
    配合使用NSOperation和NSOperationQueue也能实现多线程编程

    NSOperation和NSOperationQueue实现多线程的详细步骤
    先将须要运行的操作封装到一个NSOperation对象中
    然后将NSOperation对象加入到NSOperationQueue中
    系统会自己主动将NSOperationQueue中的NSOperation取出来
    将取出的NSOperation封装的操作放到一条新线程中运行
     
    2.NSOperation的子类
    NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类

    使用NSOperation子类的方式有3种
    NSInvocationOperation
    NSBlockOperation
    自己定义子类继承NSOperation,实现内部对应的方法
     
    3.NSInvocationOperation
    创建NSInvocationOperation对象
    - (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;

    调用start方法開始运行操作
    - (void)start;
    一旦运行操作,就会调用target的sel方法

    注意
    默认情况下,调用了start方法后并不会开一条新线程去运行操作。而是在当前线程同步运行操作
    仅仅有将NSOperation放到一个NSOperationQueue中,才会异步运行操作
     
    4.NSBlockOperation
    创建NSBlockOperation对象
    + (id)blockOperationWithBlock:(void (^)(void))block;

    通过addExecutionBlock:方法加入很多其它的操作
    - (void)addExecutionBlock:(void (^)(void))block;

    注意:仅仅要NSBlockOperation封装的操作数 > 1。就会异步运行操作
     
    5.NSOperationQueue
    NSOperationQueue的作用
    NSOperation能够调用start方法来运行任务。但默认是同步运行的
    假设将NSOperation加入到NSOperationQueue(操作队列)中。系统会自己主动异步运行NSOperation中的操作

    加入操作到NSOperationQueue中
    - (void)addOperation:(NSOperation *)op;
    - (void)addOperationWithBlock:(void (^)(void))block;
     
    6.最大并发数
    什么是并发数
    同一时候运行的任务数
    比方。同一时候开3个线程运行3个任务,并发数就是3

    最大并发数的相关方法
    - (NSInteger)maxConcurrentOperationCount;
    - (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
     
    7.队列的取消、暂停和恢复
    取消队列的全部操作
    - (void)cancelAllOperations;
    提示:也能够调用NSOperation的- (void)cancel方法取消单个操作

    暂停和恢复队列
    - (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列
    - (BOOL)isSuspended;
     
    8.操作优先级
    设置NSOperation在queue中的优先级。能够改变操作的运行优先级
    - (NSOperationQueuePriority)queuePriority;
    - (void)setQueuePriority:(NSOperationQueuePriority)p;

    优先级的取值
    NSOperationQueuePriorityVeryLow = -8L,
    NSOperationQueuePriorityLow = -4L,
    NSOperationQueuePriorityNormal = 0,
    NSOperationQueuePriorityHigh = 4,
    NSOperationQueuePriorityVeryHigh = 8
     
    9.操作依赖
    NSOperation之间能够设置依赖来保证运行顺序
    比方一定要让操作A运行完后,才干运行操作B,能够这么写
    [operationB addDependency:operationA]; // 操作B依赖于操作A

    能够在不同queue的NSOperation之间创建依赖关系
     
    10.操作监听
    能够监听一个操作的运行完成
    - (void (^)(void))completionBlock;
    - (void)setCompletionBlock:(void (^)(void))block;
     
    11.自己定义NSOperation
    自己定义NSOperation的步骤非常easy
    重写- (void)main方法,在里面实现想运行的任务

    重写- (void)main方法的注意点
    自己创建自己主动释放池(由于假设是异步操作,无法訪问主线程的自己主动释放池)
    常常通过- (BOOL)isCancelled方法检測操作是否被取消,对取消做出响应

    B.使用自己定义NSOperation后台下载图片
    实现效果例如以下:



    1.思路
     
    Image(37)
     
     
    2.实现步骤[dian wo xia zai资源分不足下方留邮箱]
    (1)自己定义一个继承NSOperation的类。实现main方法,在main方法中编写任务事件
    //
    //  HVWDownloadImageOperation.h
    //  ConcurrentDownloadImageDemo
    //
    //  Created by YuriyHao on 15/7/24.
    //  Copyright (c) 2015年 YuriyHao. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @class HVWDownloadImageOperation;
    
    @protocol HVWDownloadImageOperationDelegate <NSObject>
    
    @optional
    - (void) downloadImageOperation:(HVWDownloadImageOperation *) operation didFinishedDownloadWithImage:(UIImage *) image;
    
    @end
    
    @interface HVWDownloadImageOperation : NSOperation
    
    @property(nonatomic, strong) NSString *url;
    
    @property(nonatomic, strong) NSIndexPath *indexPath;
    
    @property(nonatomic, weak) id<HVWDownloadImageOperationDelegate> delegate;
    
    @end
    

    //
    //  HVWDownloadImageOperation.m
    //  ConcurrentDownloadImageDemo
    //
    //  Created by YuriyHao on 15/7/24.
    //  Copyright (c) 2015年 YuriyHao. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import "HVWDownloadImageOperation.h"
    
    
    @implementation HVWDownloadImageOperation
    
    - (void)main {
        NSLog(@"====下载图片======%@", [NSThread currentThread]);
        
        NSURL *url = [NSURL URLWithString:self.url];
        NSData *data;
        for (int i=0; i<1; i++) {
            data = [NSData dataWithContentsOfURL:url];
        }
        
        UIImage *image = [UIImage imageWithData:data];
        
        if ([self.delegate respondsToSelector:@selector(downloadImageOperation:didFinishedDownloadWithImage:)]) {
            [self.delegate downloadImageOperation:self didFinishedDownloadWithImage:image];
        }
    }
    
    @end
    

    (2)新建一个模型类。用来存储每一个cell的数据
    //
    //  HVWApp.h
    //  ConcurrentDownloadImageDemo
    //
    //  Created by YuriyHao on 15/7/24.
    //  Copyright (c) 2015年 YuriyHao. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface HVWApp : NSObject
    
    @property(nonatomic, strong) NSString *name;
    @property(nonatomic, strong) NSString *icon;
    @property(nonatomic, strong) NSString *download;
    
    - (instancetype) initWithDictionary:(NSDictionary *) dict;
    + (instancetype) appWithDictionary:(NSDictionary *) dict;
    
    @end
    

    (3)在控制器中编写调用任务、队列进行多线程并发后台下载图片的操作
    //
    //  ViewController.m
    //  ConcurrentDownloadImageDemo
    //
    //  Created by YuriyHao on 15/7/24.
    //  Copyright (c) 2015年 YuriyHao. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "HVWApp.h"
    #import "HVWDownloadImageOperation.h"
    
    @interface ViewController () <UITableViewDataSource, UITableViewDelegate, HVWDownloadImageOperationDelegate>
    
    @property(nonatomic, strong) NSArray *apps;
    
    @property(nonatomic, strong) NSOperationQueue *queue;
    
    @property(nonatomic, strong) NSMutableDictionary *operations;
    @property(nonatomic, strong) NSMutableDictionary *images;
    
    @end
    
    @implementation ViewController
    
    - (NSArray *)apps {
        if (nil == _apps) {
            NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
            
            NSMutableArray *appArray = [NSMutableArray array];
            for (NSDictionary *dict in dictArray) {
                HVWApp *app = [HVWApp appWithDictionary:dict];
                [appArray addObject:app];
            }
            _apps = appArray;
        }
        return _apps;
    }
    
    - (NSOperationQueue *)queue {
        if (_queue == nil ) {
            _queue = [[NSOperationQueue alloc] init];
            _queue.maxConcurrentOperationCount = 3;
        }
        return _queue;
    }
    
    - (NSMutableDictionary *)operations {
        if (nil == _operations) {
            _operations = [NSMutableDictionary dictionary];
        }
        return _operations;
    }
    
    - (NSMutableDictionary *)images {
        if (nil == _images) {
            _images = [NSMutableDictionary dictionary];
        }
        return _images;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    #pragma mark - tableViewDatasource
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return self.apps.count;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *ID = @"AppCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        
        if (nil == cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:ID];
        }
        
        HVWApp *app = self.apps[indexPath.row];
        cell.textLabel.text = app.name;
        cell.detailTextLabel.text = app.download;
        
        // 占位图片
        cell.imageView.image = [UIImage imageNamed:@"a9ec8a13632762d0092abc3ca2ec08fa513dc619"];
        
        // 假设没有图片,准备开启线程下载图片
        UIImage *image = self.images[app.icon];
        
        if (image) {
            // 假设图片存在,不须要反复下载,直接设置图片
            cell.imageView.image = image;
        } else {
            
            // 假设图片不存在。看看是不是正在下载
            HVWDownloadImageOperation *operation = self.operations[app.icon];
            
            if (operation) {
                // 假设图片正在下载,不必要开启线的线程再进行下载
            } else {
                
                // 没有在下载,创建一个新的任务进行下载
                operation = [[HVWDownloadImageOperation alloc] init];
                // 设置代理
                operation.delegate = self;
                // 传送url
                operation.url = app.icon;
                // 记录indexPath
                operation.indexPath = indexPath;
                
                [self.queue addOperation:operation];
                
                // 记录正在下载的任务
                [self.operations setObject:operation forKey:operation.url];
            }
        }
        
        return cell;
    }
    
    #pragma mark - HVWDownloadImageOperationDelegate
    - (void)downloadImageOperation:(HVWDownloadImageOperation *)operation didFinishedDownloadWithImage:(UIImage *)image {
        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:operation.indexPath];
        cell.imageView.image = image;
        [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];
        
        // 存储图片到内存
        if (image) {
            [self.images setObject:image forKey:operation.url];
        }
        
        NSLog(@"已经下载的图片数==========>%d", self.images.count);
    }
    
    @end
    

    郝萌主倾心贡献,尊重作者的劳动成果。请勿转载。

    假设文章对您有所帮助。欢迎给作者捐赠。支持郝萌主,捐赠数额任意,重在心意^_^ 

    我要捐赠: 点击捐赠

    Cocos2d-X源代码下载:点我传送

    游戏官方下载:http://dwz.cn/RwTjl

    游戏视频预览:http://dwz.cn/RzHHd

    游戏开发博客:http://dwz.cn/RzJzI

    游戏源代码传送http://dwz.cn/Nret1

  • 相关阅读:
    centos 安装 谷歌BBR
    centos上mailx通过465端口发送邮件
    centos 6的LAMP一键安装包(可选择/升级版本)
    Linux 一键安装最新内核并开启 BBR 脚本
    CentOS 7安装Xfce和VNC
    重构手法之简化函数调用【4】
    重构手法之简化函数调用【3】
    重构手法之简化函数调用【2】
    重构手法之简化函数调用【1】
    重构手法之简化条件表达式【4】
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6726249.html
Copyright © 2011-2022 走看看