Reputation: 1291
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
)
Upvotes: 1
Views: 1353
Reputation: 41622
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];
...
}
Upvotes: 3