Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 取消调度\u组\u通知_Ios_Grand Central Dispatch - Fatal编程技术网

Ios 取消调度\u组\u通知

Ios 取消调度\u组\u通知,ios,grand-central-dispatch,Ios,Grand Central Dispatch,我有一个iOS应用程序,在某些情况下,它会向服务器创建多个请求以填充屏幕。为了加快速度,我们使请求同时运行。为此,我们使用了dispatch_group_enter、dispatch_group_leave和dispatch_group_notify来确保在返回所有答案之前不会填充屏幕: performRequest1() // calls dispatch_group_enter before sending the request and dispatch_group_leave wh

我有一个iOS应用程序,在某些情况下,它会向服务器创建多个请求以填充屏幕。为了加快速度,我们使请求同时运行。为此,我们使用了dispatch_group_enter、dispatch_group_leave和dispatch_group_notify来确保在返回所有答案之前不会填充屏幕:

   performRequest1() // calls dispatch_group_enter before sending the request and dispatch_group_leave when receiving the response
   performRequest2() // calls dispatch_group_enter before sending the request and dispatch_group_leave when receiving the response
   dispatch_group_notify(dispatchGroup, dispatch_get_main_queue()) {
       populateScreen()
   }
当用户在收到两个服务器请求的响应之前按下后退按钮时,就会出现问题。在这种情况下,我们有一个自动取消服务器请求的设置(1),因此我的成功/失败块不被调用(2)。因此,永远不会调用调度组离开。我认为这很好(我不希望调用populateScreen()方法)。但iOS似乎有一种防止信号量在返回初始状态之前释放的机制(3)。换句话说,我被迫呼叫调度组,输入的次数与调度组离开的次数完全相同。即使在我只想跳过和解除锁定的情况下

由于将“取消”操作发送到执行上述代码的视图控制器(4)将是对我的应用程序的一次重大检修,我想听听是否有人有更好的替代方案,以便等待多个请求完成加载?或者是否有更好的方法使用调度\组\进入/离开

编辑

以下几点澄清(回应@Rob Napier的回答):

(1) cancel是使用AFNetworkings内置的AFHTTPRequestOperation.cancel()函数实现的

(2) 当发送取消操作时,AFNetworking当然会调用故障块。但是在我处理的遗留代码中,有一个网络层处理cancel操作,因此不会将失败发送给执行请求的类。正如@Rob Napier所说,这很可能是错误的根源,但在大型应用程序中改变这种架构设计需要一点勇气…:-|因此,我希望有一个解决方案,在释放viewController时,我可以“中止”等待的populateScreen()调用

(3) 我知道这篇文章指的是有点不同的东西。然而,我们的应用程序中的崩溃导致Xcode停止在与该帖子中代码完全相同的位置:

       0x110bab17a <+61>:  jne    0x110bab19c               ; <+95>
       0x110bab17c <+63>:  leaq   0x189d0(%rip), %rcx       ; "BUG IN CLIENT OF LIBDISPATCH: Use-after-free of dispatch_semaphore_t"
       0x110bab183 <+70>:  movq   %rcx, 0x23316(%rip)       ; gCRAnnotations + 8
       0x110bab18a <+77>:  ud2    
       0x110bab18c <+79>:  leaq   0x18972(%rip), %rcx       ; "BUG IN CLIENT OF LIBDISPATCH: Semaphore/group object deallocated while in use"
       0x110bab193 <+86>:  movq   %rcx, 0x23306(%rip)       ; gCRAnnotations + 8
   ->  0x110bab19a <+93>:  ud2    
0x110bab17a:jne 0x110bab19c;
0x110bab17c:leaq 0x189d0(%rip),%rcx;“LIBDISPATCH客户端中的错误:在释放dispatch\u信号量\u t后使用”
0x110bab183:movq%rcx,0x23316(%rip);gCRAnnotations+8
0x110bab18a:ud2
0x110bab18c:leaq 0x18972(%rip),%rcx;“LIBDISPATCH客户端中的错误:在使用时释放信号量/组对象”
0x110bab193:movq%rcx,0x23306(%rip);gCRAnnotations+8
->0x110bab19a:ud2
好吧,这可能不是iOS中的一个bug,只是一个非常烦人的设计决策;-)


(4) 这大大简化了我们的应用程序的整个架构。更准确地说:我们有一个服务层,它执行网络请求并创建返回到视图控制器的模型:-)

首先,这不是一个bug。您提供的链接正在讨论相关但不同的
dispatch\u信号量。在该线程中,他们注意到即使这也不是一个bug。文档很清楚:“对[dispatch\u group\u enter]的调用必须与对dispatch\u group\u leave的调用保持平衡。”这是预期的行为

在这种情况下,我们有一个自动取消服务器请求的设置,因此不会调用我的成功/失败块

这是个错误。无论您在这里所说的“取消”是什么意思,都应该生成一个故障条件,从而导致调用故障块。例如,如果在
NSURLSessionTask
上调用
cancel
,代理将收到一个错误。您的
performRequest()
也需要这样做。您是如何实现“取消”的

这意味着取消时将调用
populateScreen()
。这应该没问题,因为您的系统必须已经能够处理请求错误,而取消只是另一种错误


作为一个单独的问题,如果上面的代码在视图控制器中,它可能位于错误的位置。视图控制器不应进行网络调用并等待结果。他们应该只观察他们的模型。无论模型何时更改,它们都应该更改。他们应该将用户的请求传递给模型,并让模型与网络对话。在这种特殊情况下,这可能只是将问题从视图控制器转移到模型,因此可能不会有太大的改变。但这意味着视图控制器应该能够在取消完成之前取消分配。这一点很重要,因为视图控制器在弹出后不必保留。

如何使用NSOperationQueue。您可以将请求设置为任务。设置可以同时执行并在必要时取消的任务数。AFNetworking提供了这种实现。请看一看,它的名称是
AFHTTPRequestOperation
,非常感谢您的建议。我没有意识到AFNetworking中可能有一个内置的功能。我来看看!谢谢你详尽的回答。我已对我的问题进行了编辑,以包括对您观点的回答。您可能是对的,根本原因是我没有向发出请求的服务发送取消错误。但我希望找到另一种解决方案,不必重新测试整个应用程序的取消操作;-)