何时在应用程序中调用completionHandler:performFetchWithCompletionHandler:当背景获取是asynchronous?

我有一个应用程序,在背景获取的帮助下获取内容。

所以如果一个后台抓取应该发生我的application:performFetchWithCompletionHandler:方法被调用。 在这个方法中,我使用NSURLConnection来获取asynchronous的内容。

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

你是对的 – 只有当你的提取实际完成时,你才应该调用完成处理程序。 否则,iOS可能会在连接完成之前将应用程序UIBackgroundFetchResultNewData为睡眠状态,应用程序实际上无法确定UIBackgroundFetchResultNewDataUIBackgroundFetchResultNoDataUIBackgroundFetchResultFailed 。 你怎么知道你的连接会成功?

你需要保持completionHandler的状态,只有在连接完成后才能调用它。 最有可能的是你会想要添加一个实例variables到你的委托,将完成处理程序复制到那里,并在完成时调用它。

另外: connection:didReceiveData:不表示请求的结束。 根据文档:

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

[…]

委托应该连接每个交付的数据对象的内容,以构buildURL加载的完整数据。

您可能会收到任何数量的呼叫,并且URL连接的净结果是所有这些的累积。

编辑:你通过创build一个正确types的实例variables并将块复制到它来存储一个块。 块有不同寻常的语义,因为不同于其他types的Objective-C对象,它们最初是在堆栈上创build的。 最终效果就是你总是copy它们。 如果他们在复制的时候堆在一起,那么他们最终会在堆上。 如果它们已经在堆上,那么这个副本只是作为一个保留,因为块总是不变的。

所以:

 @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