iOS启动后台线程

我的iOS设备上有一个小的sqlitedb。 当用户按下button时,我从sqlite获取数据并将其显示给用户。

这个提取部分我想在后台线程中做(不要阻塞UI主线程)。 我这样做是这样 –

[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];

提取和一点处理后,我需要更新用户界面。 但是,由于(作为一个好的做法),我们不应该从后台线程执行UI更新。 我就像这样在mainthread上调用一个selector

[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];

但我的应用程序在第一步崩溃。 即开始一个后台线程。 这不是在iOS中启动后台线程的方法吗?

更新1:[self performSelectorInBackground....我得到这个stacktrace,没有任何信息是如此的 –

在这里输入图像说明

更新2:我甚至尝试过,像这样开始后台线程 – [NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids]; 但我仍然得到相同的堆栈跟踪。

只是为了澄清,当我在主线程上执行这个操作时,一切都运行平稳…

更新3这是我想从后台运行的方法

 - (void)getResultSetFromDB:(NSMutableArray *)toProceessDocids { SpotMain *mirror = [[SpotMain alloc] init]; NSMutableArray *filteredDocids = toProceessDocids; if(![gMediaBucket isEqualToString:@""]) filteredDocids = [mirror FetchDocIdsForMediaBucketWithDocID:filteredDocids mBucket:gMediaBucket numRes:-1]; if(![gMediaType isEqualToString:@""]) filteredDocids = [mirror FetchDocIdsForMediaType:filteredDocids mediaType:gMediaType numRes:-1]; if(![gPlatform isEqualToString:@""]) filteredDocids = [mirror FetchDocIdsForPlatformID:filteredDocids platformId:@"1" numRes:-1]; self.resultSet = [mirror FetchObjectFromDocid:filteredDocids]; [filteredDocids release]; [mirror release]; [self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO]; return; } 

如果你使用performSelectorInBackground:withObject:产生一个新的线程,那么执行的select器负责设置新线程的自动释放池,运行循环和其他configuration细节 – 请参阅Apple的线程编程指南中的 “使用NSObject生成线程” 。

不过,使用Grand Central Dispatch可能会更好一些:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self getResultSetFromDB:docids]; }); 

GCD是一种较新的技术,在内存开销和代码行方面效率更高。


Chris Nolet 更新了一个帽子提示,他提出了一个改变,使上面的代码更简单,并跟上苹果最新的GCD代码示例。

启用NSZombieEnabled来知道哪个对象正在被释放然后被访问。 然后检查getResultSetFromDB:是否与此有关。 另外检查是否docids里面有任何东西,如果它被保留。

这样你可以肯定没有什么不对

iOS自带的默认sqlite库不是使用SQLITE_THREADSAFEmacros编译的。 这可能是你的代码崩溃的原因。

Swift 2.x回答:

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { self.getResultSetFromDB(docids) } 

GCD实际上很容易。 典型的工作stream程是这样的:

 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul); dispatch_async(queue, ^{ // Perform async operation // Call your method/function here // Example: // NSString *result = [anObject calculateSomething]; dispatch_sync(dispatch_get_main_queue(), ^{ // Update UI // Example: // self.myLabel.text = result; }); }); 

有关GCD的更多信息,您可以在这里查看Apple的文档