【问题标题】:Why is PFQuery.cancel() as part of the parse.com-Framework not working?为什么 PFQuery.cancel() 作为 parse.com-Framework 的一部分不起作用?
【发布时间】:2014-10-07 18:44:48
【问题描述】:

我找到了很多与这个主题相关的帖子,但我可能会一直做错事......

在创建query(PFQuery 的一个实例)之后,请求被实现为query.findObjects()(在后台线程上运行)。在该请求期间,我无法像 query.cancel() 方法所期望的那样取消其进程。

场景:Internet 连接丢失,query.findObjects() 尝试连接,失败,重试。我实现了在请求第一次失败时执行的query.cancel()(在上述点执行的if objects == nil 中),但它仍在进行第二次尝试。在第二次尝试后(每一次都需要大约 15 秒)失败了,不会触发第三次。

为什么会出现这种情况,为什么调用query.cancel()时进程没有中断?

感谢您的帮助!

编辑 1:一些代码

func getPost() {

    let queue = dispatch_queue_create("SerialBgQueue", DISPATCH_QUEUE_SERIAL)

    dispatch_async(queue, {

        var query = PFQuery(className: "Post")

        var objects = query.findObjects()

        if objects != nil {

            // do something

        } else {

            println("This part is executed now")

            // doesn't stop the ongoing (second) connection attempt:
            query.cancel()

           // do something

            return
        }
    })
}

编辑 2:这就是日志 - 对我来说,这看起来像是第二次尝试,检查日志(尝试 2、3、4,...然后重新开始 2、3、4,...)。 else {-part 中间执行一次,最后执行第二次。之后,一切都停止了,不再“尝试”。

2014-10-08 13:37:10.104 Instagram[9210:391955] Error: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo=0x7fe708c545c0 {NSUnderlyingError=0x7fe708c53020 "The Internet connection appears to be offline.", NSErrorFailingURLStringKey=https://api.parse.com/2/find, NSErrorFailingURLKey=https://api.parse.com/2/find, _kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, NSLocalizedDescription=The Internet connection appears to be offline.} (Code: 100, Version: 1.3.0)

2014-10-08 13:37:10.105 Instagram[9210:391952] Network connection failed. Making attempt 2 after sleeping for 1.092226 seconds.

2014-10-08 13:37:11.311 ... (Code: 100, Version: 1.3.0) // same Error like in the very first line

2014-10-08 13:37:11.312 Instagram[9210:391945] Network connection failed. Making attempt 3 after sleeping for 2.184451 seconds.

2014-10-08 13:37:13.704 ... (Code: 100, Version: 1.3.0) 

2014-10-08 13:37:13.704 Instagram[9210:391952] Network connection failed. Making attempt 4 after sleeping for 4.368902 seconds.

2014-10-08 13:37:18.514 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:18.514 Instagram[9210:391952] Network connection failed. Making attempt 5 after sleeping for 8.737804 seconds.

2014-10-08 13:37:27.257 ... (Code: 100, Version: 1.3.0)

This part is executed now

2014-10-08 13:37:27.265 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:27.266 Instagram[9210:392183] Network connection failed. Making attempt 2 after sleeping for 1.387503 seconds.

2014-10-08 13:37:28.792 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:28.793 Instagram[9210:392202] Network connection failed. Making attempt 3 after sleeping for 2.775006 seconds.

2014-10-08 13:37:31.843 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:31.844 Instagram[9210:392205] Network connection failed. Making attempt 4 after sleeping for 5.550011 seconds.

2014-10-08 13:37:37.401 ... (Code: 100, Version: 1.3.0)

2014-10-08 13:37:37.401 Instagram[9210:392202] Network connection failed. Making attempt 5 after sleeping for 11.100023 seconds.

2014-10-08 13:37:49.050 ... (Code: 100, Version: 1.3.0)

This part is executed now

【问题讨论】:

  • “(第二次)连接尝试”是什么意思? query之后还有查询吗?
  • @KhanhNguyen 检查编辑 2
  • 您无法取消它。您可以做的最好的事情是在一段时间后在某处设置_isCancelled 标志,并使用if 忽略设置的结果。
  • 无法取消的合理原因是什么?还有其他方法可以打破这个过程吗?在这种情况下,标志无济于事 - 它与停止任何(查询)过程有关。在第一次失败后,我会提醒用户。但是,如果它实际上没有停止,则内置的刷新按钮(用户偶尔会再次点击)没有任何影响。只要查询仍然处于活动状态,就可以通过一种没有影响的方式来解决这个问题,但是一些依赖于连接试验的状态/持续时间的警报会变得混乱,并且时间完全错误,这会完全混淆用户。

标签: ios parse-platform


【解决方案1】:

我认为您对findObjects() 的假设是不正确的。该品种会阻止启动它的线程(您在发布案例中的后台线程),并在成功或失败时返回。当您调用取消时,您的代码中没有什么可以取消。

典型的取消模式是代码在不同的线程上启动查询,然后决定它需要取消,就像这样(在 Objective-C 中......对不起)

PFQuery *query = [PFQuery queryWithClassName:@"Post"];    
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    // this block might get called more than once, depending on the cache policy
    // but it will be called with an error only once and stop after that
    // (no second attempt that I know about) so as far as I can tell, there's
    // no reason to ever call cancel here.
}];

假设您不希望查询时间超过 10 秒。那么……

[query performSelector:@selector(cancel) withObject:nil afterDelay:10.0];

【讨论】:

  • 我必须保留findObjects(),因为之后会有更多代码需要等待查询完成,但不能写入...inBackgroundWithBlock-part(至少在我目前经验水平)。无论如何,我会接受你的意见并继续努力。也许我的 EDIT 2 与日志提供了一些关于正在发生的事情的更多信息。
  • 在我的示例中我必须在哪里实现 performSelector 才能达到预期的效果?
  • performSelector 如果您使用 ...inBackgroundWithBlock 种类的 find 将是有意义的,然后您可以将该行放在它之前或之后。如果 parse 在重试时确实阻塞了这个后台线程,你可以保留一个标志并取消 iOS 线程。参见例如这里stackoverflow.com/questions/10066897/…
  • 我认为你应该尝试使用find的背景品种。它真的会简化事情。而且我敢打赌,我可以帮助您弄清楚如何在完成块中运行某些东西。如果您愿意,请尝试并发布一个不同的 SO 问题。在这里给我一个链接。 (请参阅旧解析论坛parse.com/questions/…
  • 其实我也想试试,对吧!我只是想指出困难是什么:在我的表格单元格中,我必须调整图像的大小,使其适合屏幕的宽度,并且还知道它适应的高度。因此,一种方法是计算所需的纵横比和得到的高度。这需要使用自动布局正确设置单元格的高度。经过大量的反复试验后,唯一没有错误的方法是确保单元配置等待整个单元内容完全准备好,然后再开始创建单元。使用这样的后台进程很难做到这一点。
猜你喜欢
  • 2021-12-07
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多