我有一个类通过NSURLConnection更新app文档目录中的两个.plist文件。该类充当NSURLConnection的自己的委托。当我要求单个文件时它正常工作,但是当我尝试更新两个文件时失败。看起来我应该为每个getNewDatabase消息启动一个新线程吗?
- (void)getAllNewDatabases {
[self performSelectorOnMainThread:@selector(getNewDatabase:) withObject:@"file1" waitUntilDone:YES];
[self performSelectorOnMainThread:@selector(getNewDatabase:) withObject:@"file2" waitUntilDone:YES];
}
- (BOOL)getNewDatabase:(NSString *)dbName
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableString *apiString = [[NSMutableString alloc] initWithString:kAPIHost];
[apiString appendFormat:@"/%@.plist",dbName];
NSURLRequest *myRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:apiString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLConnection *myConnection = [[NSURLConnection alloc] initWithRequest:myRequest delegate:self];
[apiString release];
if( myConnection )
{
//omitted for clarity here
}
[pool release];
}
//NSURLConnection delegate methods here ...
答案 0 :(得分:8)
我发现了一些有趣的NSURLConnection和NSThread - 只要执行你从中调用的方法,线程就会生存。
在上面的情况下,线程只有在getNewDatabase:(NSString *)dbName
完成时才会生存,因此在它们实际有时间做任何事情之前就会删除它的任何委托方法。
我找到了this网站,可以提供更好的解释和问题解决方案
我调整了一点,所以如果它没有在给定的时间范围内完成,我可以有一个自定义的时间(当有人在接入点之间走动时很方便)
start = [NSDate dateWithTimeIntervalSinceNow:3];
while(!isFinished && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]]){
if([start compare:[NSDate date]] == NSOrderedAscending){
isFinished = YES;
}
}
答案 1 :(得分:4)
目前在您提供的代码中,getNewDatabase:
正在您的应用程序的主线程上运行。在这种特殊情况下的问题不仅仅是线程的生命周期,正如James在他的案例中所观察到的那样。
如果您打算在后台执行此操作,我建议您尝试使用NSOperationQueue
和NSOperation
而不是解决当前代码的问题。我认为你的案例非常适合NSOperationQueue
,特别是考虑到你有多个下载任务要执行。
Dave Dribin在NSOperation
内部使用异步API(例如NSURLConnection)excellent article。或者,只要您在后台线程中运行,您也可以简化流程并在NSOperation中使用同步API方法,例如initWithContentsOfURL:
。
Marcus Zarra也written a tutorial证明了将NSOperationQueue合并到简单的后台操作是多么容易。