Reputation: 2941
Below is the method with the code, where I am getting a memory leak using manual memory management. The memory leak is detected by using Xcode instruments and specifically points to the line where I am using NSJSONSerialization. I am running the target app (on a device with iOS 6.1).
The first time that i tap on the refreshButton there is no leak. Any subsequent tap generates the leak(and more leaks on top of that if i continue tapping the button). Below is the code - This is basic stuff for consuming JSON web services(the web service link is bogus but the real one that I am using works). You will notice that I am using Grand Central Dispatch so that I can update the UI without waiting for the parsing of the JSON to finish.
The line detected by instruments is surrounded by the asterisks. I would like to get some help to anyone who might have an idea of what is going on here. The full stack trace(as mentioned in the below comments i will put here:)
+(NSJSONSerialization JSONObjectWithData:option:error:] -> -[_NSJSONReader parseData:options:] -> -[_NSJSONReader parseUTF8JSONData:skipBytes:options]->newJSONValue->newJSONString->[NSPlaceholderString initWithBytes:length:encoding:]
-(void)parseDictionary:(NSDictionary *)dictonary{
self.transactions = [dictonary objectForKey:@"transactions"];
if(!self.transactions){
NSLog(@"Expected 'transactions' array");
return;
}
for (int arrayIndex = 0; arrayIndex < [self.transactions count]; arrayIndex++) {
TransactionResult *result = [[[TransactionResult alloc] init] autorelease];
result.transactionID = [[self.transactions objectAtIndex:arrayIndex] objectForKey:@"ID"];
result.transactionDescription = [[self.transactions objectAtIndex:arrayIndex] objectForKey:@"description"];
result.transactionPrice = [[self.transactions objectAtIndex:arrayIndex] objectForKey:@"price"];
self.totalPrice += [result.transactionPrice doubleValue];
NSLog(@"total price: %f", self.totalPrice);
[self.transactionResults addObject:result];
result = nil;
}
}
- (IBAction)refreshButtonPressed:(UIBarButtonItem *)sender {
__block id resultObject;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
NSURL *url = [NSURL URLWithString:@"http://mywebservice.php"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
***resultObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];***
if(!error){
if([resultObject isKindOfClass:[NSDictionary class]]){
NSDictionary *dictonary = resultObject;
[self parseDictionary:dictonary];
NSLog(@"Done parsing!");
dispatch_async(dispatch_get_main_queue(), ^{
self.isLoading = NO;
[self.transactionsTableView reloadData];
});
}
else{
NSLog(@"JSON Error: Expected Dictionary");
resultObject = nil;
return;
}
}
else{
NSLog(@"JSON Error: %@", [error localizedDescription]);
dispatch_async(dispatch_get_main_queue(), ^{
resultObject = nil;
[self.transactionsTableView reloadData];
[self showError];
});
return;
}
});
}
Upvotes: 2
Views: 1341
Reputation: 41652
I used a ARC as soon as it came out with 4.3, and put an app in the store with it - point being you could switch to ARC. That said, I tried to reproduce your problem by creating a class/file that has the no-arc flag applied to it, but cannot reproduce the problem. This makes me believe your problem is elsewhere. In the code below, I create a Test object in another file, retain it, and send it the test message. No matter what I set "i" to, it always deallocs the object:
#import "Tester.h"
@interface Obj : NSObject <NSObject>
@end
@implementation Obj
- (id)retain
{
NSLog(@"retain");
id i = [super retain];
return i;
}
- (oneway void)release
{
NSLog(@"release");
[super release];
}
- (void)foo
{
}
- (void)dealloc
{
NSLog(@"Obj dealloced");
[super dealloc];
}
@end
@implementation Tester
- (void)test
{
int i = 2;
__block Obj *obj;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
obj = [[Obj new] autorelease];
if(i == 0) {
Obj *o = obj;
dispatch_async(dispatch_get_main_queue(), ^
{
[o foo];
} );
} else if(i == 1) {
obj = nil;
} else if(i == 2) {
dispatch_async(dispatch_get_main_queue(), ^
{
obj = nil;
} );
}
} );
}
@end
Upvotes: 0