iOS start Background Thread

Srikar Appalaraju picture Srikar Appalaraju · Aug 14, 2011 · Viewed 168.8k times · Source

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

Answer

Scott Forbes picture Scott Forbes · Aug 14, 2011

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.