我的 iOS 设备中有一个小型 sqlitedb。当用户按下按钮时,我从 sqlite & 获取数据。将其显示给用户。
我想在后台线程中执行此获取部分(以免阻塞 UI 主线程)。我这样做 -
getResultSetFromDB:) withObject:docids];
[self PerformSelectorInBackground:@selector ( 稍微处理一下,我需要更新UI。但因为(作为一个好的实践)我们不应该从后台线程执行 UI 更新。我像这样在主线程上调用选择器
-
[self PerformSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
但我的应用程序在第一步崩溃了。即启动后台线程。这不是iOS启动后台线程的方法吗?
更新1:在[self PerformSelectorInBackground....
之后我得到了这个堆栈跟踪,没有任何信息 -
![在此处输入图像描述](https://i.sstatic.net /C1AaS.png)
更新 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;
}
I have a small sqlitedb in my iOS device. When a user presses a button, I fetch the data from sqlite & show it to user.
This fetching part I want to do it in a background thread (to not block the UI main thread). I do this like so -
[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];
After the fetching & a little bit of processing, I need to update the UI. But since (as a good practice) we should not perform UI updation from background threads. I call a selector
on mainthread like so -
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
But my App crashes in the first step. i.e. starting a background thread. Is this not a way to start background threads in iOS?
UPDATE 1: After [self performSelectorInBackground....
I get this stacktrace, no info what so ever -
![enter image description here](https://i.sstatic.net/C1AaS.png)
UPDATE 2: I even tried, starting a background thread like so -
[NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];
but still I get same stacktrace.
Just so that I clarify, when I perform this operation on main thread everything runs smooth...
UPDATE 3 This is the method I am trying to run from background
- (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;
}
发布评论
评论(5)
如果您使用
performSelectorInBackground:withObject:
生成一个新线程,则执行的选择器负责设置新线程的自动释放池、运行循环和其他配置详细信息 - 请参阅Apple 的线程编程指南中的“使用 NSObject 生成线程”。您可能最好使用 Grand Central Dispatch:
GCD 是一项较新的技术,并且在内存开销和代码行方面更加高效。
已更新,向 Chris Nolet 致敬,他提出了一项更改,使上述内容得以实现代码更简单,并跟上Apple最新的GCD代码示例。
If you use
performSelectorInBackground:withObject:
to spawn a new thread, then the performed selector is responsible for setting up the new thread's autorelease pool, run loop and other configuration details – see "Using NSObject to Spawn a Thread" in Apple's Threading Programming Guide.You'd probably be better off using Grand Central Dispatch, though:
GCD is a newer technology, and is more efficient in terms of memory overhead and lines of code.
Updated with a hat tip to Chris Nolet, who suggested a change that makes the above code simpler and keeps up with Apple's latest GCD code examples.
其实用 GCD 来说这很简单。典型的工作流程如下:
有关 GCD 的更多信息,您可以查看 Apple 文档位于此处
Well that's pretty easy actually with GCD. A typical workflow would be something like this:
For more on GCD you can take a look into Apple's documentation here
启用 NSZombieEnabled 来了解哪个对象正在被使用释放然后访问。
然后检查 getResultSetFromDB: 是否与此有关。还要检查
docids
内部是否有任何内容以及是否被保留。这样您就可以确定没有任何问题。
Enable NSZombieEnabled to know which object is being released and then accessed.
Then check if the
getResultSetFromDB:
has anything to do with that. Also check ifdocids
has anything inside and if it is being retained.This way you can be sure there is nothing wrong.
iOS 自带的默认 sqlite 库不是使用 SQLITE_THREADSAFE 宏编译的。这可能是您的代码崩溃的原因。
The default sqlite library that comes with iOS is not compiled using the SQLITE_THREADSAFE macro on. This could be a reason why your code crashes.
斯威夫特 2.x 答案:
Swift 2.x answer: