我使用了大中央调度(GCD)方法来实现这一点。这是一个在一个简单的测试应用程序中对我有用的示例(我不确定它是否适用于静态库,但可能值得一看)。我正在使用ARC。
在示例中,我从 viewDidLoad 方法开始了一些后台工作,但您可以从任何地方开始它。关键是“dispatch_async(dispatch_get_global_queue ...”在后台线程中运行该块。有关该方法的良好解释,请参阅此答案:https ://stackoverflow.com/a/12693409/215821
这是我的viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL),
^(void) {
[self doStuffInBackground];
});
}
此时 doStuffInBackground 方法正在后台运行,因此您可以同步使用 NSURLConnection 。在我的示例中,该方法循环进行网络调用,直到可能有其他代码设置 backgroundStuffShouldRun = false。使用 10 秒超时进行网络调用。通话结束后,我正在更新 UI 标签以显示进度。请注意,UI 更新是使用“dispatch_async(dispatch_get_main_queue()...”执行的。这会根据需要在 UI 线程上运行 UI 更新。
此背景工作的一个潜在问题是:无法取消 http 请求本身。但是,如果有 10 秒的超时,那么在外部人员(可能是您的 UI 中的某些事件)设置 backgroundStuffShouldRun = false 之后,您将等待最多 10 秒的时间让线程自行中止。
- (void)doStuffInBackground
{
while (backgroundStuffShouldRun) {
// prepare for network call...
NSURL* url = [[NSURL alloc] initWithString:@"http://maps.google.com/maps/geo"];
// set a 10 second timeout on the request
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:10];
NSError* error = nil;
NSURLResponse *response = nil;
// make the request
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// were we asked to stop the background processing?
if (!backgroundStuffShouldRun) {
return;
}
// process response...
NSString* status = @"Success";
if (error) {
if (error.code == NSURLErrorTimedOut) {
// handle timeout...
status = @"Timed out";
}
else {
// handle other errors...
status = @"Other error";
}
}
else {
// success, handle the response body
NSString *dataAsString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", dataAsString);
}
// update the UI with our status
dispatch_async(dispatch_get_main_queue(), ^{
[statusLabel setText:[NSString stringWithFormat:@"completed network call %d, status = %@", callCount, status]];
});
callCount++;
sleep(1); // 1 second breather. not necessary, but good idea for testing
}
}