从嵌套的NSOperations调用cancelAllOperations

时间:2016-06-14 11:49:39

标签: ios swift nsoperation nsoperationqueue

我在以下情况下挣扎,请求我,因为我试图尽可能清楚地解释这一点:

我有一个CoummintyOperation类,它是GroupOperation的子类。调用CommuityOperation并将其添加到NSOperationQueue。 CommunityOperation反过来调用了一大堆NSOperations,它们也是GroupOperation的子句,反过来又在其中调用NSoperations。 我已经在CommunityOperation类中添加了GroupOperations的依赖项。 我正在处理的问题是如果嵌套操作失败,我需要在CommunityOperations类中取消所有NSOperations,但是我无法访问为添加CommunityOperation而调用cancelAllOperations方法的operationQueue

任何人都可以帮我解释如何调用此方法,取消此类中的所有操作(以及所有嵌套操作)并向用户显示错误消息。

提前致谢

以下是帮助解释我的问题的示例代码: CommunityOperation从另一个类(不包括在内)中放入一个operationQueue

public class CommunityOperation: GroupOperation {

    var updateOperation: UpdateOperation!
    var menuOperation: MenuOperation!
    var coreDataSaveOperation: CoreDataSaveOperation!

    var hasErrors = false

    public init() {

        super.init(operations: [])

        updateOperation = UpdateOperation()
        menuOperation = MenuOperation()
        coreDataSaveOperation = CoreDataSaveOperation()
        coreDataSaveOperation.addDependencies([updateOperation, menuOperation])

        self.addOperation(updateOperation)
        self.addOperation(menuOperation)
        self.addOperation(coreDataSaveOperation)
    }
}

MenuOperation类,其中也包含嵌套操作:

class UpdateMenuOperation: GroupOperation {

    let downloadGroupsOperation: DownloadGroupsOperation
    let downloadMembersOperation: DownloadMembersOperation

    init() {
            downloadGroupsOperation = DownloadGroupsOperation()
            downloadMembersOperation = DownloadMembersOperation(])

            super.init(operations: [downloadGroupsOperation,
                downloadMembersOperation
                ])
        }
}

DownloadGroupOperation类又是GroupOperation的子类。它有2个操作 - 第一个下载数据,第二个解析数据:

class DownloadTopGroupsOperation: GroupOperation {
    let downloadOperation: DownloadOperation
    let importTopGroupsOperation: ImportOperation

    init() {
        downloadOperation = DownloadOperation()
        importOperation = ImportOperation()
        importOperation.addDependency(downloadOperation)
        importOperation.addCondition(NoCancelledDependencies())

        super.init(operations: [downloadOperation, importOperation])
    }
}

最后(哇)DownloadOperation类使用NSURLSession和方法downloadTaskWithURL,它在这个方法的完成处理程序中,如果出现错误,我想在主operatioQueue上调用cancelAllOperations退回:

class DownloadOperation: GroupOperation {
    init() {
        super.init(operations: [])
        if self.cancelled {
            return
       }
        let task = session.downloadTaskWithURL(url) { [weak self] url, response, error in
            self?.downloadFinished(url, response: response as? NSHTTPURLResponse, error: error)
        }
    }

    func downloadFinished(url: NSURL?, response: NSHTTPURLResponse?, error: NSError?) {

       if error {
         *cancel allOperations on queue*
       }
    }
}

2 个答案:

答案 0 :(得分:0)

它应该以一种不同的方式工作。我会在每次isCancelled执行结束时检查GroupOperation中的NSOperation。如果操作被取消,则取消当前GroupOperation,依此类推。最后,您的CommunityOperation也应该被取消。

以下是建议解决方案的粗略实施:

extension GroupOperation {

    func addCancellationObservers() {
        self.operations.forEach() { $0.willCancelObservers.append() {  [unowned self] operation, errors in
            self.cancel() // cancel the group operation. will force it to cancel all child operations
            }
        }
    }

}

然后从您拥有的每个群组操作的addCancellationObservers方法中调用init

答案 1 :(得分:0)

如果您使用Apple的示例代码(或https://github.com/danthorpe/Operations这是该项目的演变),您可以通过将条件附加到具有依赖项的操作来对其进行排序。

以下是您的顶级GroupOperation

的初始化
init() {

    updateOperation = UpdateOperation()
    menuOperation = MenuOperation()
    coreDataSaveOperation = CoreDataSaveOperation()
    coreDataSaveOperation.addDependencies([updateOperation, menuOperation])

    // Attach a condition to ensure that all dependencies succeeded
    coreDataSaveOperation.addCondition(NoFailedDependenciesCondition())

    super.init(operations: [updateOperation, menuOperation, coreDataSaveOperation])
}

要解释这里发生的事情...... NSOperation没有“失败”的概念。操作总是“完成”但是它们是成功完成还是失败并不会影响NSOperation依赖项的工作方式。

换句话说,无论这些依赖项是否成功,操作都将在所有依赖项完成时就绪。这是因为“成功”和“失败”是子类必须定义的东西。 OperationNSOperation子类)通过完成而没有任何错误来定义成功。

要处理此问题,请添加一个条件,确保没有依赖项必须失败。在操作中,这个条件被重命名以使其更清晰。但是,这个概念也存在于Apple示例代码中。