何时在应用程序中调用completionHandler:performFetchWithCompletionHandler:当背景获取是asynchronous?
我有一个应用程序,在背景获取的帮助下获取内容。
所以如果一个后台抓取应该发生我的application:performFetchWithCompletionHandler:
方法被调用。 在这个方法中,我使用NSURLConnection来获取asynchronous的内容。
在我目前的实现中,我只启动请求,然后用UIBackgroundFetchResultNewData
调用UIBackgroundFetchResultNewData
。 我知道这是不对的。 所以我的问题是,当asynchronous请求完成connection:didReceiveData:
方法时,如何正确调用completionHandler
。
你是对的 – 只有当你的提取实际完成时,你才应该调用完成处理程序。 否则,iOS可能会在连接完成之前将应用程序UIBackgroundFetchResultNewData
为睡眠状态,应用程序实际上无法确定UIBackgroundFetchResultNewData
与UIBackgroundFetchResultNoData
或UIBackgroundFetchResultFailed
。 你怎么知道你的连接会成功?
你需要保持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