iOS开发多线程基础知识 NSOperation

-------NSOperation简介----

1.NSOperation的作用

·配合使用NSOperation和NSOperationQueue也能实现多线程编程

2.NSOperation和NSOperationQueue实现多线程的具体步骤

·先将需要执行的操作封装到一个NSOperation对象中

·然后将NSOperation对象添加到NSOperationQueue中

·系统会自动将NSOperation中封装的操作放到一条新线程中执行

---------NSOperation的子类----

3.NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类

4.使用NSOperation子类的方式有3种

·NSInvocationOperation

·NSBlockOperation

·自定义子类继承NSOperation,实现内部相应的方法

------NSInvocationOperation---

5.创建NSInvocationOperation对象

- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;

6.调用start方法开始执行操作

- (void)start;

一旦执行操作,就会调用target的sel方法

7.注意

·默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作

·只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作

-------NSBlockOperation--

8.创建NSBlockOperation对象

+ (id)blockOperationWithBlock:(void (^)(void))block;

9.通过addExecutionBlock:方法添加更多的操作

- (void)addExecutionBlock:(void (^)(void))block;

注意:只要NSBlockOperation封装的操作数 > 1,就会异步执行操作

-------NSOperationQueue----

10.NSOperationQueue的作用

·NSOperation可以调用start方法来执行任务,但默认是同步执行的

·如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作

11.添加操作到NSOperationQueue中

- (void)addOperation:(NSOperation *)op;

- (void)addOperationWithBlock:(void (^)(void))block;

-------最大并发数----

12.什么是并发数

·同时执行的任务数

·比如,同时开3个线程执行3个任务,并发数就是3

13.最大并发数的相关方法

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

-----队列的取消、暂停、恢复------

14.取消队列的所有操作

- (void)cancelAllOperations;

提示:也可以调用NSOperation的- (void)cancel方法取消单个操作

15.暂停和恢复队列

- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列

- (BOOL)isSuspended;

----操作优先级-----

16.设置NSOperation在queue中的优先级,可以改变操作的执行顺序

- (NSOperationQueuePriority)queuePriority;

- (void)setQueuePriority:(NSOperationQueuePriority)p;

17.优先级的取值(优先级越高,越先执行)

·NSOperationQueuePriorityVeryLow = -8L,

·NSOperationQueuePriorityLow = -4L,

·NSOperationQueuePriorityNormal = 0,

·NSOperationQueuePriorityHigh = 4,

·NSOperationQueuePriorityVeryHigh = 8

---操作依赖---

18.NSOperation之间可以设置依赖来保证执行顺序

·比如一定要让操作A执行完后,才能执行操作B,可以这么写

[operationB addDependency:operationA]; // 操作B依赖于操作A

19.可以在不同queue的NSOperation之间创建依赖关系

20.注意:不能相互依赖

·比如A依赖B,B依赖A

----操作的执行顺序---

21.对于添加到queue中的operations,它们的执行顺序取决于2点

·首先依据NSOperation之间的依赖关系

·然后依据NSOperation的优先级

22.因此,总体的执行顺序是

·先满足依赖关系

·然后再从NSOperation中选择优先级最高的那个执行

---自定义NSOperation---

23.自定义NSOperation的步骤很简单

·重写- (void)main方法,在里面实现想执行的任务

24.重写- (void)main方法的注意点

·自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)

·经常通过- (BOOL)isCancelled方法检测操作是否被取消,对取消做出响应

--------分割线---

NSOperation小代码1,

只写一个文件参考下

//  DYFViewController.m
//  624-03-NSOperation
//
//  Created by dyf on 14-6-24.
//  Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved.
//

#import "DYFViewController.h"

@interface DYFViewController ()

@end

@implementation DYFViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.

    [self testOperationQueue];
}

- (void)testOperationListen {
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载图片1111111%@", [NSThread currentThread]);
        // 下载图片
    }];
    operation3.completionBlock = ^{
        // 下载完图片后想做的时期
    };
    // 2.创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    [queue addOperation:operation3];

}

- (void)testOperationQueue {
    // 1.封装操作
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
    NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1111111%@", [NSThread currentThread]);
    }];

    [operation3 addExecutionBlock:^{
        NSLog(@"222222%@", [NSThread currentThread]);
    }];
    [operation3 addExecutionBlock:^{
        NSLog(@"33333%@", [NSThread currentThread]);
    }];
    // 2.创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 5以内,2~3为宜
    queue.maxConcurrentOperationCount = 2;
#warning 面试题
    // 设置操作依赖(一定要在添加到队列中前设置)
    [operation2 addDependency:operation1]; // 执行顺序取决于依赖,先执行完operation1再执行operation2
// 注意:不能相互依赖,循环操作

    // 3.添加操作到队列中(自动执行操作,自动开启线程)
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];

    // 取消所有线程
    //[queue cancelAllOperations];

    // 暂停队列
    //[queue setSuspended:YES];

    // 设置操作优先级
    //operation1.queuePriority = NSOperationQueuePriorityVeryHigh;

}

- (void)testNSBlockOperation {
    // 1.创建操作对象,封装要执行的任务
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 11; i++) {
            NSLog(@"1111111%@", [NSThread currentThread]);
        }
    }];
    // 任务数在2各以上,就会开线程
    [operation addExecutionBlock:^{
        for (int i = 0; i < 11; i++) {
            NSLog(@"222222%@", [NSThread currentThread]);
        }
    }];
    [operation addExecutionBlock:^{
        for (int i = 0; i < 11; i++) {
            NSLog(@"33333%@", [NSThread currentThread]);
        }
    }];

    // 2.执行操作
    [operation start];
}

- (void)testNSInvocationOperation {
    // 1.创建操作对象,封装要执行的任务
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
    // 2.执行操作(默认情况下,若操作没有放到队列queue中,都是同步执行)
    [operation start];
}

- (void)download
{
    for (int i = 0; i < 11; i++) {
        NSLog(@"download-----%@", [NSThread currentThread]);
    }
}

- (void)run
{
    for (int i = 0; i < 11; i++) {
        NSLog(@"run------%@", [NSThread currentThread]);
    }
}

@end

----自定义NSOperation---

//
//  DYFDownloadOperation.h
//  624-05-自定义Operation
//
//  Created by dyf on 14-6-24.
//  Copyright (c) 2014年 dyf. All rights reserved.
//

#import <Foundation/Foundation.h>

@class DYFDownloadOperation;
@protocol DYFDownloadOperationDelegate <NSObject>

@optional
- (void)downloadOperation:(DYFDownloadOperation *)operation didFinishedDownload:(UIImage *)image;

@end

@interface DYFDownloadOperation : NSOperation

@property (nonatomic, copy) NSString *url;
@property (nonatomic, strong) NSIndexPath *indexPath;

@property (nonatomic, weak) id<DYFDownloadOperationDelegate> delegate;

@end
//
//  DYFDownloadOperation.m
//  624-05-自定义Operation
//
//  Created by dyf on 14-6-24.
//  Copyright (c) 2014年 dyf. All rights reserved.
//

#import "DYFDownloadOperation.h"

@implementation DYFDownloadOperation
/**
 *  在main方法中实现具体操作
 */
- (void)main
{
    @autoreleasepool {
        if (self.isCancelled) return;
        NSURL *imaUrl = [NSURL URLWithString:self.url];
        if (self.isCancelled) return;
        // 下面这行很耗时
        NSData *data = [NSData dataWithContentsOfURL:imaUrl];
        if (self.isCancelled) return;
        UIImage *image = [UIImage imageWithData:data];
        if (self.isCancelled) return;

        // 返回主线程显示图片
        // 通过代理
        if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishedDownload:)]) {
            [self.delegate downloadOperation:self didFinishedDownload:image];
        }
    }
}

@end

具体利用MVC模式创建的文件老生常谈,只来一个Controller.m文件供参考,数据存储存在问题,可以改用SDWebImage框架处理

//
//  DYFTableViewController.m
//  624-05-自定义Operation
//
//  Created by dyf on 14-6-24.
//  Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved.
//

#import "DYFTableViewController.h"
#import "DYFAppModel.h"
#import "DYFDownloadOperation.h"

#warning Dictionary基础知识不太理解,字典的赋值回去看看笔记
@interface DYFTableViewController ()<DYFDownloadOperationDelegate>

@property (nonatomic, strong) NSArray *apps;
@property (nonatomic, strong) NSOperationQueue *queue;

/**
 *  key:url   value:operation对象
 */
@property (nonatomic, strong) NSMutableDictionary *oprations;
/**
 *  key:url   value:image对象
 */
@property (nonatomic, strong) NSMutableDictionary *images;

@end

@implementation DYFTableViewController

#pragma mark - 4个懒加载
- (NSArray *)apps
{
    if (!_apps) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"];
        NSArray *arrayApps = [NSArray arrayWithContentsOfFile:path];

        NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:arrayApps.count];
        for (NSDictionary *dict in arrayApps) {
            DYFAppModel *appM = [DYFAppModel appWithDict:dict];
            [arrayM addObject:appM];
        }
        _apps = arrayM;
    }
    return _apps;
}
- (NSOperationQueue *)queue
{
    if (!_queue) {
        _queue = [[NSOperationQueue alloc] init];
        // 设置最大并发线程数,最多同时下载3张图片
        _queue.maxConcurrentOperationCount = 3;
    }
    return _queue;
}
- (NSMutableDictionary *)oprations
{
    if (!_oprations) {
        _oprations = [[NSMutableDictionary alloc] init];
    }
    return _oprations;
}
- (NSMutableDictionary *)images
{
    if (!_images) {
        _images = [NSMutableDictionary dictionary];
    }
    return _images;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
}

#pragma mark - 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.apps.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 1.创建cell
    static NSString *identifier = @"apps";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
    }
    // 2.设置cell的数据
    DYFAppModel *app = self.apps[indexPath.row];
    cell.textLabel.text = app.name;
    cell.detailTextLabel.text = app.download;

    // 重点是如何从网络下载图片传入cell上面
    // 每个url对应一个DYFDownloadOperation对象
    // 每个url对应一个image对象
    UIImage *image = self.images[app.icon];
    if (image) {
        // 若缓存中存在图片
        cell.imageView.image = image;
    }else
    {
        // 若缓存中不存在图片,则图片要从网上下载
        // 设置下载前系统刷出的图片
        cell.imageView.image = [UIImage imageNamed:@"身份证小"];

        // 基础差,下面这行不太理解
        DYFDownloadOperation *operation = self.oprations[app.icon];
        if (operation) {
            // 若正在下载,则不执行其它操作
        }else
        {
            // 若没在下载,则创建开始下载的子线程
            DYFDownloadOperation *operation = [[DYFDownloadOperation alloc] init];
            operation.url = app.icon;
            operation.indexPath = indexPath;
            operation.delegate = self;
            // 添加任务进队列,异步下载
            [self.queue addOperation:operation];
            // 基础差,下面这行不太理解
            self.oprations[app.icon] = operation;
        }
    }

    // 3.返回cell
    return cell;
}

#pragma mark - DYFDownloadOperationDelegate
- (void)downloadOperation:(DYFDownloadOperation *)operation didFinishedDownload:(UIImage *)image
{
    // 1.删除执行完毕的下载操作
    [self.oprations removeObjectForKey:operation.url];
    // 若图片下载好
    if (image) {
        // 2.将下载好的图片存入缓存
        self.images[operation.url] = image;
        // 3.刷新这一行cell的数据
        [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];
        // 4.将图片存入沙盒

        // 4.1图片先转换为2进制数据
        NSData *data = UIImagePNGRepresentation(image);
        // 4.2设置沙盒路径
        NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[self.apps[operation.indexPath.row] icon]];
        NSLog(@"%@", path);
        // 4.3保存data到path中
        [data writeToFile:path atomically:YES];
    }
}

// 开始拖拽时候暂停队列
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.queue setSuspended:YES];
}
// 停止拖拽的时候重启队列
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    [self.queue setSuspended:NO];
}

@end

iOS开发多线程基础知识 NSOperation,布布扣,bubuko.com

时间: 2024-10-22 18:04:19

iOS开发多线程基础知识 NSOperation的相关文章

iOS开发多线程基础知识

--------------------------多线程概念基础------- 进程:正在运行的程序 内存:每个进程所占的存储空间 线程:1个进程要像执行任务,必须得有线程,线程是进程的基本执行单元, 线程的串行: ·1个线程中人物的执行是串行的 ·0同一个时间内,1个线程只能执行1个任务 0·线程是进程的一条执行路径 --------多线程 ·一个进程中可以开启多条线程,每条线程可以并行(同时)同时执行不同的任务 ·进程->车间 线程->车间工人 线程的并行: ·进程内多个线程同时执行,可

iOS开发多线程之自定义NSOperation

iOS开发多线程篇—自定义NSOperation 一.实现一个简单的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 rig

iOS开发多线程篇—自定义NSOperation

iOS开发多线程篇—自定义NSOperation 一.实现一个简单的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 rig

iOS开发多线程篇 09 —NSOperation简单介绍

iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作?:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤: (1)先将需要执行的操作封装到一个NSOperation对象中 (2)然后将NSOperation对象添加到NSOperationQueue中 (3)系统会?动将NSOperationQueue中的NSOpe

iOS开发多线程篇 10 —NSOperation基本操作

iOS开发多线程篇—NSOperation基本操作 一.并发数 (1)并发数:同时执?行的任务数.比如,同时开3个线程执行3个任务,并发数就是3 (2)最大并发数:同一时间最多只能执行的任务的个数. (3)最?大并发数的相关?方法 - (NSInteger)maxConcurrentOperationCount;- (void)setMaxConcurrentOperationCount:(NSInteger)cnt; 说明:如果没有设置最大并发数,那么并发的个数是由系统内存和CPU决定的,可能

ios开发多线程四:NSOperation多图下载综合案例

#import "ViewController.h" #import "XMGAPP.h" @interface ViewController () /** tableView的数据源 */ @property (nonatomic, strong) NSArray *apps; /** 内存缓存 */ @property (nonatomic, strong) NSMutableDictionary *images; /** 队列 */ @property (no

IOS研究之IOS开发笔记基础知识学习

本文是我的IOS学习笔记,都是基础的知识点,在这里记录下方面以后查询. 1,UIScrollView视图类能完成滚动的功能. 示例如下: UIScrollView *tableScrollView; tableScrollView=[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];//窗口大小 tableScrollView.contentSize=CGSizeMake(640, 480);//设置内容视图的大小 ta

【iOS开发-多线程】使用NSOperation创建线程(使用较多)

NSOperation NSOperation封装了GCD的一些操作,使用更加面向对象的方式实现多线程 创建多线程的步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加到NSOperationQueue中 系统会自动将NSOperationQueue中的NSOperation取出来 NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类 NSInvocationOperation NSBlockOperation 自定义子类继承

iOS开发多线程编程2 - NSOperation

1.简介 NSOperation实例封装了需要执行的操作和执行操作所需的数据,并且能够以并发或非并发的方式执行这个操作. NSOperation本身是抽象基类,因此必须使用它的子类,使用NSOperation子类的方式有2种: 1> Foundation框架提供了两个具体子类直接供我们使用:NSInvocationOperation和NSBlockOperation 2> 自定义子类继承NSOperation,实现内部相应的方法 2.执行操作 NSOperation调用start方法即可开始执