gpt4 book ai didi

ios - 当 NSOperationQueue 中的所有其他操作完成时执行 NSOperation,无论它们是否成功完成

转载 作者:搜寻专家 更新时间:2023-10-31 22:13:12 24 4
gpt4 key购买 nike

嗨,我这里有一个奇怪的情况:

概览:

我正在开发一个用户可以启动多个操作的应用程序,所有这些操作都将在后台线程上运行,因此不会阻塞 UI。这些操作中有些是相互依赖的,有些则不是。因此,为了确保操作仅在所有必要的依赖操作完成执行后才执行,我使用操作的依赖属性。我正在使用异步操作。

这是我的实现:

import UIKit
import CoreData
import SwiftyJSON

class VMBaseOperation: NSOperation {
var finishedStatus : Bool = false
var executionStatus : Bool = false
var retryCount : Int = 0
private (set) var requestToQueue : BaseRequest? = nil
var vmOperationCompletionBlock: ((JSON?) -> Void)?
var vmOperationFailureBlock: ((WebResponseError?) -> Void)?

override init() {
super.init()
}

convenience init(withVMRequest request : BaseRequest) {
self.init()
requestToQueue = request
}

override func start() {
if self.cancelled {
self.finished = true
return
}
NSThread.detachNewThreadSelector(#selector(main), toTarget: self, withObject: nil)
self.executionStatus = true
}


override func main() {
if self.cancelled {
return
}
self.hitWebService()
}

func hitWebService(){
let webserviceManager = WebServiceManager()
webserviceManager.getResponseFromRequest(requestToQueue!) { (requset, response, data, error) in
let error = WebResponseError.checkResponse(response, request: requset, error: error)
if error != nil {
if error == WebResponseError.NO_INTERNET {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(error)
}
self.operationFailed()
}
else{
self.retryCount += 1
if self.retryCount == 3 {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(error)
}
self.operationFailed()
}
else{
self.hitWebService()
}
}
}
else{
if data == nil {
self.retryCount += 1
if self.retryCount == 3 {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(nil)
}
self.operationFailed()
}
else{
self.hitWebService()
}
}
else{
let json = JSON(data: data!)
if self.vmOperationCompletionBlock != nil {
self.vmOperationCompletionBlock!(json)
}
self.operationCompleted()
}
}
}
}

override var finished: Bool {
get{
return finishedStatus
}
set{
self.willChangeValueForKey("isFinished")
finishedStatus = newValue
self.didChangeValueForKey("isFinished")
}
}

override var executing: Bool {
get{
return executionStatus
}
set{
self.willChangeValueForKey("isExecuting")
executionStatus = newValue
self.didChangeValueForKey("isExecuting")
}
}


override var asynchronous: Bool{
get{
return true
}
set{
self.willChangeValueForKey("isAsynchronous")
self.asynchronous = true
self.didChangeValueForKey("isAsynchronous")
}
}

func operationCompleted(){
self.executing = false
self.finished = true
}

func operationFailed(){
self.executing = false
self.finished = false
}
}

它的作用:

每个操作接受一个网络请求并尝试从服务器获取数据,如果失败,它会尝试 3 次,然后通过调用 operationFailed 方法最终将其完成状态设置为 false,然后停止所有操作依赖操作永远不会执行。另一方面,如果成功,它会通过调用 operationCompleted 将其完成状态更改为 true,从而触发其余依赖操作的执行。

问题是什么:

依赖就像一种魅力。没问题。现在我需要在操作队列中的所有操作完成执行时从服务器同步数据,无论它们是否成功完成。

最简单的方法是创建一个操作来同步来自服务器的数据,并将其作为依赖操作添加到添加到 operationQueue 的所有操作中。

但是由于上述操作的性质,即使一个操作全部失败,它也会停止所有相关操作的执行(正如预期的那样),但是因为我来自服务器操作的同步数据也是一个相关操作,它永远不会执行即使一个操作失败:(

我需要什么:

在维护我上面提到的依赖性的同时,我需要知道当操作队列中的所有操作完成执行时,无论它们成功还是失败,如何执行操作以从服务器同步数据。

这是否可能 :( 请帮帮我。在此先感谢。

最佳答案

没关系,我想通了:)

将完成状态设置为 true 和 false 会触发 NSOperationQueue 的 KVO,从而启动或取消依赖操作的操作。

如果我希望我的操作在任何时候执行,无论依赖操作是否成功完成,我都不能使用 finished 标志。在这种情况下,完成标志应始终为真,以指示操作已完成执行。

但是我将如何确保对那些设置了依赖项的操作的正则链的管理,并且实际上取决于之前的操作是否成功?很简单,我在我的 NSOperationSubclass 中添加了另一个名为 finishedSuccessfully 的变量。

当操作失败时,虽然它会将完成标志设置为 true,但它会将 finishedSuccessfully 设置为 false。这将导致依赖操作启动方法被调用。

在依赖操作的start方法中,它会遍历所有的依赖操作,并检查它们是否都完成了finishedSuccessfully = true。

如果是,则表示所有依赖操作都已完成执行并成功完成,因此可以开始执行。另一方面,如果它们中的任何一个已 finishedSuccessfully = false,这意味着操作已完成执行但未能完成它应该做的任何事情,因此该操作也应该停止自身并通知其依赖者它已完成 finishedSuccessfully = false。

总结:

  1. 只有在所有依赖操作执行完毕后,操作才会执行,无论它们是否成功完成。

  2. 真正关心其依赖操作执行状态的操作会检查状态,然后最终决定是否继续执行。

维护依赖链以及同步操作执行的确认:)

这是我的实现:

import UIKit
import CoreData
import SwiftyJSON

class VMBaseOperation: NSOperation {
var finishedSuccessfully : Bool = false
var finishedStatus : Bool = false
var executionStatus : Bool = false
var retryCount : Int = 0

private (set) var requestToQueue : BaseRequest? = nil
var vmOperationCompletionBlock: ((JSON?) -> Void)?
var vmOperationFailureBlock: ((WebResponseError?) -> Void)?

override init() {
super.init()
}

convenience init(withVMRequest request : BaseRequest) {
self.init()
requestToQueue = request
}

override func start() {
if self.cancelled {
self.finished = true
return
}
//those operations which actually wants to know if all its dependency operations finished successfully or not can create a subclass of this class override start method and add the below code
for operation in self.dependencies {
if (operation as! VMBaseOperation).finishedSuccessfully == false {
self.operationFailed()
return
}
}
//others can ignore.
NSThread.detachNewThreadSelector(#selector(main), toTarget: self, withObject: nil)
self.executionStatus = true
}


override func main() {
if self.cancelled {
return
}
self.hitWebService()
}

func hitWebService(){
let webserviceManager = WebServiceManager()
webserviceManager.getResponseFromRequest(requestToQueue!) { (requset, response, data, error) in
let error = WebResponseError.checkResponse(response, request: requset, error: error)
if error != nil {
if error == WebResponseError.NO_INTERNET {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(error)
}
self.operationFailed()
}
else{
self.retryCount += 1
if self.retryCount == 3 {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(error)
}
self.operationFailed()
}
else{
self.hitWebService()
}
}
}
else{
if data == nil {
self.retryCount += 1
if self.retryCount == 3 {
if self.vmOperationFailureBlock != nil {
self.vmOperationFailureBlock!(nil)
}
self.operationFailed()
}
else{
self.hitWebService()
}
}
else{
let json = JSON(data: data!)
if self.vmOperationCompletionBlock != nil {
self.vmOperationCompletionBlock!(json)
}
self.operationCompleted()
}
}
}
}

override var finished: Bool {
get{
return finishedStatus
}
set{
self.willChangeValueForKey("isFinished")
finishedStatus = newValue
self.didChangeValueForKey("isFinished")
}
}

override var executing: Bool {
get{
return executionStatus
}
set{
self.willChangeValueForKey("isExecuting")
executionStatus = newValue
self.didChangeValueForKey("isExecuting")
}
}

override var asynchronous: Bool{
get{
return true
}
set{
self.willChangeValueForKey("isAsynchronous")
self.asynchronous = true
self.didChangeValueForKey("isAsynchronous")
}
}

func operationCompleted(){
self.executing = false
self.finished = true
}

func operationFailed(){
self.finishedSuccessfully = false
self.operationCompleted()
}

func operationSucceeded(){
self.finishedSuccessfully = true
self.operationCompleted()
}
}

关于ios - 当 NSOperationQueue 中的所有其他操作完成时执行 NSOperation,无论它们是否成功完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39201284/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com