Ios 在NSOperationQueue中的所有其他操作完成时执行NSOperation,无论它们是否成功完成
嗨,我这里有个奇怪的情况: 概述: 我正在开发一个应用程序,用户可以启动多个操作,所有这些操作都将在后台线程上运行,因此不会阻塞UI。这些操作中有些相互依赖,有些则互不依赖。 因此,为了确保操作仅在所有必要的依赖项操作使用operation的dependency属性执行完am之后执行。我正在使用异步操作 以下是我的实现:Ios 在NSOperationQueue中的所有其他操作完成时执行NSOperation,无论它们是否成功完成,ios,swift,nsoperation,nsoperationqueue,Ios,Swift,Nsoperation,Nsoperationqueue,嗨,我这里有个奇怪的情况: 概述: 我正在开发一个应用程序,用户可以启动多个操作,所有这些操作都将在后台线程上运行,因此不会阻塞UI。这些操作中有些相互依赖,有些则互不依赖。 因此,为了确保操作仅在所有必要的依赖项操作使用operation的dependency属性执行完am之后执行。我正在使用异步操作 以下是我的实现: import UIKit import CoreData import SwiftyJSON class VMBaseOperation: NSOperation {
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
}
}
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()
}
}
它的作用:
每个操作都会接受一个web请求并尝试从服务器获取数据,如果失败,它尝试了3次,最后通过调用operationFailed
方法将其完成状态设置为false,然后停止所有相关操作永远执行。另一方面,如果成功,则通过调用operationCompleted
将其完成状态更改为true,从而触发剩余操作的执行依赖操作
问题是什么:
依赖就像一种魅力。没问题。现在,当操作队列中的所有操作都完成执行时,无论它们是否成功完成,我都需要从服务器同步数据
最简单的方法是创建一个从服务器同步数据的操作,并将其作为从属操作添加到添加到operationQueue的所有操作中
但是,由于操作的上述性质,即使一个操作失败,它也会停止所有依赖操作的执行(如预期),但由于服务器操作中的“我的同步数据”也是一个依赖操作,因此即使一个操作失败,它也不会执行:(
我需要什么:
在维护我上面提到的依赖关系的同时,我需要知道如何在操作队列中的所有操作完成时执行一个操作来同步来自服务器的数据,无论这些操作是成功还是失败
这可能吗:(请帮我解决。提前谢谢。没关系,我想出来了:) 将finished status设置为true和false将触发NSOperationQueue的KVO,从而启动或取消依赖操作的操作 如果我想在任何时候执行我的操作,无论依赖项操作是否成功完成,我都不能使用finished标志。在这种情况下,finished标志应该始终为true,以指示操作已完成执行 但是,对于那些设置了依赖项的操作,我将如何确保其体面链的管理,这实际上取决于上一个操作是否成功??很简单,我在NSOperationSubclass中添加了另一个名为finishedSuccessfully的变量 当操作失败时,尽管它将finished标志设置为true,但它将finishedSuccessfully设置为false。这将导致调用依赖操作的start方法 在依赖操作的start方法中,它将迭代所有依赖操作,并检查是否所有操作都已完成,finishedSuccessfully=true 如果是,则表示所有依赖项操作都已完成执行并成功完成,因此可以开始执行。另一方面,如果其中任何一个操作已完成成功=false,则表示操作已完成执行,但未能完成其应执行的操作,因此此操作也应自行停止并通知其用户完成finishedSuccessfully的依赖项=false 摘要:
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
}
}
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()
}
}
您的实施
操作失败
:
func operationFailed(){
self.executing = false
self.finished = false
}
您破坏了NSO操作的本机逻辑:
操作相关性
依赖关系是以特定方式执行操作的一种方便方法
秩序。可以使用添加和删除操作的依赖项
addDependency:和removeDependency:方法。默认情况下,一个操作
具有依赖项的对象在其所有
从属操作对象已完成执行。最后一次
从属操作完成后,操作对象将变为
准备好并能够执行
NSOperation支持的依赖项对
从属操作是否成功完成。
(换句话说,取消操作同样会将其标记为
已完成。)由您决定是否使用
依赖项应在其依赖操作的情况下继续进行
被取消或未成功完成任务。今年五月
要求您加入一些额外的错误跟踪功能
进入您的操作对象
根据设计,如果操作失败,它应该完成。但它可以以某种方式标记自己(某些特殊属性或被取消的属性)
相关操作应检查是否可以启动。类似于以下内容的内容应该可以完成这项工作:
var requireDependencesCompletion: Bool = true
override var ready: Bool {
if requireDependencesCompletion
{
for op in self.dependencies {
if op.cancelled {
cancel()
}
}
super.ready
}
在这里,我们重写ready
属性来确定应该做什么。如果requireDependencesCompletion
为true
则操作将检查其所有依赖项,如果其中一项被取消,则会自动取消