Question

I update my tableview by loading json result from server using NSOperationQueue

Adding queue:

- (void)AddQueue
{
   NSOperationQueue *queue = [NSOperationQueue new];
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                            selector:@selector(loadDataWithOperation)
                                                                              object:nil];
    [queue addOperation:operation];
} 

Loading result:

-(void)loadDataWithOperation{

    // Create array to hold dictionaries
    myObject = [[NSMutableArray alloc] init];

    NSData *jsonData = [NSData dataWithContentsOfURL:
                        [NSURL URLWithString:@"http://www.test.com/json.php"]];

    if(jsonData != nil)
    {
        NSError *error = nil;
        id jsonObjects = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
        if (error == nil){

            // values in foreach loop
            for (NSDictionary *dataDict in jsonObjects) {
                strPhotoID = [dataDict objectForKey:@"id"];
                strName = [dataDict objectForKey:@"title"];
                strUrl = [dataDict objectForKey:@"url"];
                strThumb = [dataDict objectForKey:@"thumb"];
                strDay = [dataDict objectForKey:@"day"];
                strDate = [dataDict objectForKey:@"date"];
                strLikes = [dataDict objectForKey:@"likes"];
                strDeviceid = [dataDict objectForKey:@"deviceid"];
                strActive = [dataDict objectForKey:@"active"];

                dict = [NSDictionary dictionaryWithObjectsAndKeys:
                        strPhotoID, photoid,
                        strName, title,
                        strThumb, thumb,
                        strUrl, photourl,
                        strDay, day,
                        strDate, date,
                        strLikes, likes,
                        strDeviceid, deviceid,
                        strActive, active,
                        nil];


                [myObject addObject:dict];

                NSSortDescriptor * sortDesc = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:NO];
                [myObject sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];


                [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];

                [self performSelectorOnMainThread:@selector(endAnimating) withObject:nil waitUntilDone:YES];


            }
        }

    }


}

This code works well and load what I need, but if I load my result multiple times app crashes. I think it happens because of many operations at same time. How to prevent app crashing?

Log:

libobjc.A.dylib`_cache_getImp:
0x39a39580:  lsr.w  r9, r1, #2
0x39a39584:  ldr    r3, [r0, #8] // EXC_BAD_ACCESS
0x39a39586:  add.w  r3, r3, #8
0x39a3958a:  ldr    r12, [r3, #-8]
0x39a3958e:  and.w  r9, r9, r12
0x39a39592:  ldr.w  r0, [r3, r9, lsl #2]
0x39a39596:  teq.w  r0, #0
0x39a3959a:  add.w  r9, r9, #1
0x39a3959e:  beq    0x39a395b2                ; _cache_getImp + 50
0x39a395a0:  ldr.w  r12, [r0]
0x39a395a4:  teq.w  r1, r12
0x39a395a8:  bne    0x39a3958a                ; _cache_getImp + 10
0x39a395aa:  ldr.w  r12, [r0, #8]
0x39a395ae:  mov    r0, r12
0x39a395b0:  bx     lr
0x39a395b2:  mov.w  r0, #0
0x39a395b6:  bx     lr
0x39a395b8:  nop    
0x39a395ba:  nop    
0x39a395bc:  nop    
0x39a395be:  nop    

Stack trace:

(
    0   testApp                             0x000ddd09 -[Perjantai loadDataWithOperation] + 72
    1   CoreFoundation                      0x31d46ad4 <redacted> + 68
    2   CoreFoundation                      0x31c9e28f <redacted> + 290
    3   Foundation                          0x32647f65 <redacted> + 112
    4   Foundation                          0x325d1a89 <redacted> + 840
    5   Foundation                          0x32649fe7 <redacted> + 102
    6   libdispatch.dylib                   0x39e58793 <redacted> + 10
    7   libdispatch.dylib                   0x39e5c657 <redacted> + 278
    8   libdispatch.dylib                   0x39e5c7d9 <redacted> + 92
    9   libsystem_c.dylib                   0x39e807f1 <redacted> + 360
    10  libsystem_c.dylib                   0x39e80684 start_wqthread + 8
)
Was it helpful?

Solution

In your first block of code, you allocate the queue, but don't keep a strong reference to it, so it gets realloced right away. Create an ivar, create one queue early on, and add objects to it as needed. Using ARC the ivar will get released on its own, but in your dealloc you probably want to either wait for all operations to complete, or cancel them then wait - to avoid a different crash.

CODE:

@implementation myClass
{
  NSOperation *q;
}

- (id)init....
...
    q = [NSOperationQueue new];
...
  return self;
}

- (void)dealloc
{
  [q cancelAllOperations];
  [q waitUntilAllOperationsAreFinished];
  ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top