- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
嗨,我这里有一个奇怪的情况:
概览:
我正在开发一个用户可以启动多个操作的应用程序,所有这些操作都将在后台线程上运行,因此不会阻塞 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。
总结:
只有在所有依赖操作执行完毕后,操作才会执行,无论它们是否成功完成。
真正关心其依赖操作执行状态的操作会检查状态,然后最终决定是否继续执行。
维护依赖链以及同步操作执行的确认:)
这是我的实现:
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/
我在 crashlytics 中得到了一些我完全不明白的崩溃报告,这是崩溃线程的崩溃日志: 我没有找到任何关于我的代码的提示,它也不是可重现的或只发生在特定设备上的东西。根据 Crashlytics
我需要从 JSON 下载数据,并将数据分配给 NSOperationQueue 之外的 NSData。这是我的代码: -(void)parsingInfo { NSURL *url = [NS
我有一个应用程序,其中一个长时间运行的进程(> 1 分钟)被放置在 NSOperationQueue(队列 A)上。当队列 A 操作运行时,UI 完全响应,完全符合预期。 但是,我有一种用户可以执行的
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 1年前关闭。 Improve this
我有几个后台任务需要处理,同时仍保持 UI 响应。我开始走上创建和管理线程的道路,但很快就遇到了 NSOperations。听起来是一个更好的解决方案。 。 . 但是,我似乎无法获得对 NSOpera
我想知道释放 ivar NSOperationQueue 的正确方法是什么,以防它仍有一些操作正在运行,这种情况通常在用户突然退出应用程序时发生。在一些示例中,我看到使用了 waitUntilAllO
我正在努力解决这个问题,所以我的问题是: 当我像这样实例化 NSOperationQueue 时: NSOperationQueue * operationQueue = [[NSOperationQ
我第一次尝试基于 Swift/NSOperationQueue 的设计,我正在尝试找出如何维护跨队列的数据完整性。 我处于设计过程的早期阶段,但该架构可能会涉及一个队列(称为sensorQ),用于处理
我正在寻找一种重新排序 NSOperationQueue 的方法。 我可以取消所有操作并按照我想要的顺序将它们扔回去,但我希望有一些更干净的东西。有什么想法吗? 最佳答案 NSOperationQue
我是iPhone新手。在哪里可以找到NSOperationQueue和NSOperation的示例?NSOperationQueue和NSOperation与线程相比有什么优势? 谢谢 最佳答案 阅读
正如 NSOperationQueue 类引用所述:在 iOS 中,操作队列不使用 Grand Central Dispatch 来执行操作。它们为非并发操作创建单独的线程,并从当前线程启动并发操作。
我创建了一个NSOperationQueue子类,将maxConcurrentOperations设置为1,并将addOperation方法重写为以下内容: -(void)addOperation:(
我一直在使用 NSOperationQueue,但我遇到了非常奇怪的内存问题。我已经尝试将问题减少到最简单的问题,在这里我得到了: 在初始化中: _queue = [[NSOperationQueue
我最近开始学习 Swift 中的多线程,我想使用 NSOperationQueue 和 NSOperation 类尝试一些基本的多线程。 在 .swift 文件的全局范围内(在 Xcode 中的命令行
我的任务是清理项目中一些现有的 Swift 代码,这些代码刚刚转换为 Swift 3。但是,我不断看到这个对我来说看起来很可疑的代码。 OperationQueue().addOperation(so
我正在开发一个应用程序,该应用程序从使用 performSelectorInBackground 启动的单独线程中的循环调用 AudioServicesPlayAlertSound(kSystemSo
我在我的应用程序中使用了 NSOperation 子类,它将在单个操作中执行以下 4 个任务,我希望所有这 4 个任务都在后台线程上运行,所以我将其封装到单个 NSOperation 类,这样我就可以
我在暂停当前正在执行的任务时遇到问题,我尝试设置 NSOperationQueue setSuspended=YES 暂停和 setSuspended=NO恢复进程。 根据 apple docs我不能
我正在使用 NSOperationQueue 执行并发下载并插入到核心数据中。 下面是代码,我正在使用 if(nil==queue) { queue=[[NSOperationQueue al
我正在为 ios 进行调整(显示来自网络的一些图像),并且我正在尝试使用 NSOperationQueue。首先,我在主线程上运行了一些代码来看看它是什么样子。显示每个图像持续了 ±5 秒(UI 卡住
我是一名优秀的程序员,十分优秀!