IOS 启动后台线程

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

这个获取部分我想在一个后台线程中完成(不要阻塞 UI 主线程)。我是这样做的

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

在获取和一些处理之后,我需要更新 UI。但是因为(作为一个好的实践)我们不应该从后台线程执行 UI 更新。我在主线上调用 selector就像这样

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

但我的应用程序在第一步就崩溃了。例如,启动一个后台线程。这难道不是在 iOS 中启动后台线程的一种方式吗?

更新1: [self performSelectorInBackground....之后我得到了这个堆栈跟踪,没有任何信息

enter image description here

更新2: 我甚至尝试了,启动了一个像 so-这样的后台线程 [NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids]; but still I get same stacktrace.

只是为了澄清一下,当我在主线程上执行这个操作时,一切都运行得很顺利..。

UPDATE 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;
}
171527 次浏览

启用 启用 NSZombieEnable以了解正在释放哪个对象,然后对其进行访问。 然后检查 getResultSetFromDB:是否与此有关。还要检查 docids里面是否有东西,是否被保留。

This way you can be sure there is nothing wrong.

如果使用 performSelectorInBackground:withObject:生成新线程,那么执行的选择器负责设置新线程的自动发布池、运行循环和其他配置细节——参见苹果的 线程编程指南中的 “使用 NSObject 生成线程”

不过,你最好使用 中央车站调度中心:

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

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


更新 ,向 Chris Nolet致敬,Chris Nolet提出了一个改变,使上面的代码更加简单,并与苹果最新的 GCD 代码示例保持一致。

上的 SQLITE _ THREADSAFE 宏编译 iOS 附带的默认 SQLITE 库。这可能是代码崩溃的原因之一。

迅捷的2.x 版答案:

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

实际上,这对 GCD 来说非常简单。一个典型的工作流程是这样的:

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 的信息,可以看看 苹果的文档在这里