iOS Concurrency-依赖、取消任务
发布日期:2022-03-18 08:27:39 浏览次数:50 分类:技术文章

本文共 4583 字,大约阅读时间需要 15 分钟。

iOS Concurrency-依赖、取消任务

承接

依赖(Dependencies)

简单的讲就是一个任务依赖另一个任务,常用方法:

public class Operation : NSObject {    public func addDependency(op: Operation)    public func removeDependency(op: Operation)    public var dependencies: [Operation] { get }    ...}

还是紧接上一节中的例子,现有两个Operation,一个从网络下载图片的ImageLoadOperation,一个是处理的图片的TiltShiftOperation。下面的例子是先

有个问题,就是如何在多个operation之间传递数据,把一个operation的输出作为一个operation的输入

1.使用另一个operation来传递数据

//加载图片let imageLoad = ImageLoadOperation()//处理图片let filter = TiltShiftOperation()imageLoad.inputName = "train_day.jpg"//传递数据的operationlet dataTransferOp = BlockOperation {     filter.inputImage = imageLoad.outputImage}//添加依赖filter.addDependency(dataTransferOp)dataTransferOp.addDependency(imageLoad)//添加operation到OperationQueuelet queue = OperationQueue()duration {  queue.addOperations([imageLoad, dataTransferOp, filter], waitUntilFinished: true)}

2.提供一个协议,ImageLoadOperation实现这个协议,用来传递数据

//协议protocol FilterDataProvider {    var image: UIImage? { get }}extension ImageLoadOperation: FilterDataProvider{    var image: UIImage? {        return outputImage    }}//修改TiltShiftOperationclass TiltShiftOperation: Operation {    var inputImage: UIImage?    var outputImage: UIImage?    override func main() {        if let dependencyImageProvider = dependencies            .filter({ $0 is FilterDataProvider })            .first as? FilterDataProvider,            inputImage == .none {            inputImage = dependencyImageProvider.image        }        outputImage = tiltShift(image: inputImage)    }}//加载图片let imageLoad = ImageLoadOperation()//处理图片let filter = TiltShiftOperation()filter.addDependency(imageLoad)let queue = OperationQueue()duration {  queue.addOperations([imageLoad, filter], waitUntilFinished: true)}

取消任务

cancel()方法取消operation,调用cancel()方法并不会立即停止执行operation,调用cancel()只是把isCancelled属性设为true。如果operation还没有开始运行,那么默认的start实现会阻止operation的运行,并把isFinished设置为true。所以如果你重写start方法,也要这么做,就是要阻止已经cancel的operation。

OperationQueue中的cancelAllOperations()会取消队列中所有的operation

1.如有一个ArraySumOperation,对输入数组的中的元素进行相加操作slowAdd,所以要在for循环中处理isCancelled的操作,如下:

public func slowAdd(_ input: (Int, Int)) -> Int {  sleep(1)  return input.0 + input.1}class ArraySumOperation: Operation {    //输入的数组    let inputArray: [(Int, Int)]    //输出的数组    var outputArray = [Int]()    init(input: [(Int, Int)]) {        inputArray = input        super.init()    }    override func main() {        for pair in inputArray        {            //如果isCancelled直接取消            if isCancelled {                return            }            outputArray.append(slowAdd(pair))        }    }}

2.还有一种情况是,假设现在不是slowAdd,而是slowAddArray,即直接对数组进行处理,而不是数组中元素,此时就不能在循环中判断isCancelled,如下:

public func slowAddArray(_ input: [(Int, Int)], progress: ((Double) -> (Bool))? = nil) -> [Int] {    var results = [Int]()    for pair in input {        results.append(slowAdd(pair))        if let progress = progress {            if !progress(Double(results.count) / Double(input.count)) { return results }        }    }    return results}

这个时候,只能在回调中处理cancel,如下:

class AnotherArraySumOperation: Operation {    let inputArray: [(Int, Int)]    var outputArray: [Int]?    init(input: [(Int, Int)]) {        inputArray = input        super.init()    }    override func main() {        outputArray = slowAddArray(inputArray, progress: { (progress) -> (Bool) in            print("\(progress * 100)% of the array processed")            return !self.isCancelled        })    }}

3.如下,GroupAdd管理operation queue和多个SumOperations,计算相加的结果,并添加结果到一个输出数组,管理队列的开始和取消,可作为参考

class GroupAdd {    //操作队列    let queue = OperationQueue()    //串行队列    let appendQueue = OperationQueue()    var outputArray = [(Int, Int, Int)]()    init(input: [(Int, Int)]) {        queue.isSuspended = true        queue.maxConcurrentOperationCount = 2        appendQueue.maxConcurrentOperationCount = 1        generateOperations(input)    }    func generateOperations(_ numberArray: [(Int, Int)]) {        for pair in numberArray {            //相加SumOperation            let operation = SumOperation(input: pair)            //计算完成的block            operation.completionBlock = {                guard let result = operation.output else { return }                self.appendQueue.addOperation {                    self.outputArray.append((pair.0, pair.1, result))                }            }            queue.addOperation(operation)        }    }    //开始    func start() {        queue.isSuspended = false    }    //取消    func cancel() {        queue.cancelAllOperations()    }    func wait() {        queue.waitUntilAllOperationsAreFinished()    }}

转载地址:https://windzen.blog.csdn.net/article/details/52763561 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:iOS Concurrency-Operation
下一篇:Having fun with NSOperations in iOS

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月06日 04时52分05秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章