Objective c iOS启动后台线程
我的iOS设备中有一个小sqlitedb。当用户按下按钮时,我从sqlite获取数据并将其显示给用户 这个获取部分我想在后台线程中完成(不阻塞UI主线程)。我是这样做的-Objective c iOS启动后台线程,objective-c,ios,multithreading,uikit,core-foundation,Objective C,Ios,Multithreading,Uikit,Core Foundation,我的iOS设备中有一个小sqlitedb。当用户按下按钮时,我从sqlite获取数据并将其显示给用户 这个获取部分我想在后台线程中完成(不阻塞UI主线程)。我是这样做的- [self-performSelectorInBackground:@selector(getResultSetFromDB:)with-Object:docId] 在抓取和一点处理之后,我需要更新UI。但是因为(作为一个好的实践),我们不应该从后台线程执行UI更新。我在主线程上调用选择器,如下所示- [self-perfor
[self-performSelectorInBackground:@selector(getResultSetFromDB:)with-Object:docId]代码>
在抓取和一点处理之后,我需要更新UI。但是因为(作为一个好的实践),我们不应该从后台线程执行UI更新。我在主线程上调用选择器
,如下所示-
[self-performSelectorOnMainThread:@selector(showResults),对象:nil waitUntilDone:NO]代码>
但我的应用程序在第一步就崩溃了。i、 e.启动后台线程。这不是在iOS中启动后台线程的方法吗
更新1:在[自执行选择背景…
之后,我得到了这个堆栈跟踪,没有任何信息
更新2:我甚至尝试过,像这样启动一个后台线程-
[NSThread detachNewThreadSelector:@selector(getResultSetFromDB:)toTarget:self with Object:DocId];
但我仍然得到相同的堆栈跟踪
我要澄清的是,当我在主线程上执行此操作时,一切都会顺利运行
更新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;
}
启用以了解要释放并访问的对象。
然后检查getResultSetFromDB:
是否与此有关。还要检查docids
中是否有任何内容,以及它是否被保留
通过这种方式,您可以确保没有任何错误。如果您使用performSelectorInBackground:withObject:
生成新线程,则执行的选择器负责设置新线程的自动释放池、运行循环和其他配置详细信息–请参阅《Apple线程编程指南》中的
不过,您最好使用:
GCD是一种较新的技术,在内存开销和代码行方面效率更高
更新了,建议对上述代码进行修改,使其更简单,并跟上苹果最新的GCD代码示例。iOS附带的默认sqlite库未使用上的sqlite_THREADSAFE宏编译。这可能是代码崩溃的原因。Swift 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的更多信息,您可以查看一下您得到了什么错误/崩溃日志?请查看我的更新…您可以显示您在后台调用的方法吗?并确保对象docids
被保留。是的,docids
是retain
。我已将其作为@属性(非原子,retain)放入.h
NSMutableArray*docids;
不要在方法前面加上get
;那应该是resultSetFromDB:
请复制您使用的在主线程上平稳运行的行。我从主线程使用它&至少它会命中该方法,而不是突然崩溃-[self-getResultSetFromDB:docids]
你启用了我告诉你的吗?在这行中放置一个断点:SpotMain*mirror=[[SpotMain alloc]init];并告诉我它是否命中,如果命中,哪行崩溃。请启用僵尸,这样我们就可以得到一个清晰的错误日志。是的,我启用了僵尸。我得到这个-`2011-08-14 12:49:42.697 FLO[16211:707]***-[FMResultSet release]:消息已发送到解除分配的实例0x2bff80 2011-08-14 12:49:42.697 FLO[16211:1607]***\uu NSAutoreleaseNoPool():类uu NSCFData的对象0x2c0cc0在没有池的情况下自动删除-只是泄漏。另外,当我尝试从后台线程调用此方法时,我没有到达SpotMain*mirror…`,它在进入后台线程后不久崩溃…酷!不知道这一点。这是否适用于[NSThread detachNewThreadSelector:@selector….
也是?是的。根据Apple文档,调用performSelectorInBackground:withObject:
“与调用detachNewThreadSelector:toTarget:withObject:
的(无符号长)之间有区别吗NULL
和0
在这个问题上?@Sti来自apple Dev:注意:dispatch_get_global_queue函数的第二个参数是为将来的扩展保留的。现在,这个参数应该始终传递0。然后我应该使用performSelectorOnMainThread使用操作结果更新UI,还是有更一致的方法更新UI有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;
});
});