X.X*_*per 6 asynchronous multitasking ios ios7
我有一个应用程序,在后台提取的帮助下在后台获取内容.
因此,如果应该进行后台提取,application:performFetchWithCompletionHandler:
则调用我的方法.在这个方法中,我使用NSURLConnection来异步获取内容.
在我当前的实现中,我只启动请求,然后调用completionHandler
with UIBackgroundFetchResultNewData
.我知道这不可能是正确的.所以我的问题是,如何正确调用completionHandler
async请求在connection:didReceiveData:
方法中完成的时间.
Tom*_*mmy 15
你是对的 - 只有当你的fetch实际完成时才应该调用完成处理程序.否则,iOS可能会在连接完成之前让您的应用程序重新进入休眠状态,并且应用程序实际上无法确定与之UIBackgroundFetchResultNewData
相比UIBackgroundFetchResultNoData
或UIBackgroundFetchResultFailed
之前.你怎么知道你的联系会成功?
您需要保持completionHandler并仅在连接完成后调用它.很可能你会想要为你的委托添加一个实例变量,将完成处理程序复制到那里,并在你完成后调用它.
旁白:connection:didReceiveData:
不表示请求结束.根据文件:
作为连接发送,以递增方式加载数据.
[...]
委托应该连接每个传递的数据对象的内容,以构建URL加载的完整数据.
您可能会收到任意数量的呼叫,并且URL连接的最终结果是所有呼叫的累积.
编辑:通过创建正确类型的实例变量并将块复制到其中来存储块.块具有不寻常的语义,因为与其他类型的Objective-C对象不同,它们最初是在堆栈上创建的.净效应只是你总是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
Run Code Online (Sandbox Code Playgroud)