blejzz
blejzz

Reputation: 3349

objective c perform selector in background and autoreleasepool

I am developing an iphone application which has some data stored in a sqllite database. When my view loads i would like to load the data from the database on a background thread. The problem is the application keeps crashing and i dont know why.

The code:

-(id) init
{
    if((self=[super init]))
    {
       [self performSelectorInBackground:@selector(loadList) withObject:nil];
    }
 }

-(void) loadList
{
   @autoreleasepool
   {
      Loader * loader = [[Loader alloc] init];
      NSMutableArray * array = [loader getItemList];
      [array retain];
      NSLog(@"Got %d items",[array count]);

      [self performSelectorOnMainThread:@selector(createList:) withObject:array waitUntilDone:false];
      [loader release];
   }
}

-(void) createList: (NSMutableArray*) array
{
    items = array;
    int i;
    Item * it;
    for(i = 0; i < [items count]; i++)
    {
      it = [items objectAtIndex: i];
      [it getName]; // crashes
      // populate the list
    } 
}

Loader returns a NSMutableArray with Item objects. The application crashes when i call the item getName (which returns a NSString*). From what i understand it crashes because the item name properties is being released. What am i doing wrong?

Thanks!

Upvotes: 0

Views: 1224

Answers (3)

Tommy
Tommy

Reputation: 100632

It's likely to be a problem with whatever type of object you're using to populate array.

I'm unable to find finger-on-paper proof but I'm confident that performSelectorOnMainThread:withObject:waitUntilDone: retains its object. However if each of the items in array keeps a reference to loader then they need to take responsibility for retaining that object. It looks like you're attempting to keep it alive manually but — as Chuck alludes to — your call to performSelector... will return instantly and not wait for the call you've made to complete.

Upvotes: 1

Owen Hartnett
Owen Hartnett

Reputation: 5935

I'd put a breakpoint on the line:

 it = [items objectAtIndex: i];

Then type

po it

in the debugger, and see what's in the name field. As a guess, I'd say one of two things: 1) the field that getName returns isn't initialized with an object (i.e. isn't a real NSString *) or that you're getting a C string from SQLite (which is what it usually returns) and you're trying to treat it as an NSString *. If it's the latter you can use [myCString stringWithUTF8String] to convert the C string into an NSString *

Upvotes: 0

Chuck
Chuck

Reputation: 237080

This particular bug appears to be that you're passing waitUntilDone:NO, so the array is being released immediately and consequently so are its items.

But in general, UIKit is not thread-safe, so this is just a touchy design. I would probably put the loading of this stuff in another class that handles the task for you instead of right in the view.

Upvotes: 1

Related Questions