iOS启动后台线程

发布于 2024-11-29 14:49:57 字数 1783 浏览 1 评论 0 原文

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

我想在后台线程中执行此获取部分(以免阻塞 UI 主线程)。我这样做 -

getResultSetFromDB:) withObject:docids];

[self PerformSelectorInBackground:@selector ( 稍微处理一下,我需要更新UI。但因为(作为一个好的实践)我们不应该从后台线程执行 UI 更新。我像这样在主线程上调用选择器 -

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

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

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

在此处输入图像描述

更新 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

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

国际总奸 2024-12-06 14:49:57

如果您使用performSelectorInBackground:withObject: 生成一个新线程,则执行的选择器负责设置新线程的自动释放池、运行循环和其他配置详细信息 - 请参阅Apple 的线程编程指南中的“使用 NSObject 生成线程”

您可能最好使用 Grand Central Dispatch

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

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:

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

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.

栀子花开つ 2024-12-06 14:49:57

其实用 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 的更多信息,您可以查看 Apple 文档位于此处

Well that's pretty easy actually with GCD. A typical workflow would be something like this:

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;
                });
    });

For more on GCD you can take a look into Apple's documentation here

无人问我粥可暖 2024-12-06 14:49:57

启用 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 if docids has anything inside and if it is being retained.

This way you can be sure there is nothing wrong.

卷耳 2024-12-06 14:49:57

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.

小耗子 2024-12-06 14:49:57

斯威夫特 2.x 答案:

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

Swift 2.x answer:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        self.getResultSetFromDB(docids)
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文