当后台获取异步时,何时在 application:performFetchWithCompletionHandler: 中调用completionHandler?

2024-02-16

我有一个应用程序,可以在后台获取的帮助下在后台获取内容。

因此,如果后台获取应该发生我的application:performFetchWithCompletionHandler:方法被调用。在此方法中,我使用 NSURLConnection 异步获取内容。

在我当前的实现中,我只启动请求,然后调用completionHandler with UIBackgroundFetchResultNewData。我知道这是不对的。所以我的问题是,我如何正确调用completionHandler当异步请求完成时connection:didReceiveData: method.


你是对的——只有当你的提取实际上完成时,你才应该调用完成处理程序。否则,iOS 可能会在连接完成之前让您的应用程序重新进入睡眠状态,并且应用程序实际上不应该能够确定UIBackgroundFetchResultNewData versus UIBackgroundFetchResultNoData or UIBackgroundFetchResultFailed无论如何,在那之前。您如何知道您的连接会成功?

您需要保留completionHandler,并仅在连接完成后调用它。您很可能想要向委托添加一个实例变量,将完成处理程序复制到其中,并在完成后调用它。

Aside: connection:didReceiveData:并不表示请求结束。根据文档:

作为连接发送增量加载数据。

[...]

委托应该连接每个数据对象的内容 交付用于构建 URL 加载的完整数据。

您可能会收到任意数量的呼叫,URL 连接的最终结果是所有呼叫的累积。

编辑:您通过创建正确类型的实例变量来存储块copying阻止它。块具有不寻常的语义,因为与其他类型的 Objective-C 对象不同,它们最初是在堆栈上创建的。最终的效果就是你总是copy他们。如果复制时它们在堆栈上,那么它们最终会在堆上。如果它们已经在堆上,则副本仅充当保留,因为无论如何块总是不可变的。

So:

@implementation XXMDYourClass
{
    // syntax follow the C rule; read from the centre outwards
    void (^_completionHandler)(UIBackgroundFetchResult);
}

- (id)initWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    self = [super init];

    if(self)
    {
        // keep the block by copying it; release later if
        // you're not using ARC
        _completionHandler = [completionHandler copy];
    }

    return self;
}

- (void)somethingThatHappensMuchLater
{
     _completionHandler(UIBackgroundFetchResultWhatever);
}

@end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当后台获取异步时,何时在 application:performFetchWithCompletionHandler: 中调用completionHandler? 的相关文章

随机推荐