iOS - NJSONSerialization导致内存泄漏?(根据Instruments)

时间:2013-11-17 06:41:35

标签: ios memory-management memory-leaks nsjsonserialization xcode-instruments

下面是代码的方法,我使用手动内存管理来获取内存泄漏。使用Xcode仪器检测内存泄漏,并特别指向我使用NSJSONSerialization的行。我正在运行目标应用程序(在iOS 6.1的设备上)。

我第一次点击refreshButton时没有泄漏。任何后续的敲击都会产生泄漏(如果我继续点击按钮,则会发生更多的泄漏)。下面是代码 - 这是使用JSON Web服务的基本内容(Web服务链接是虚假的,但我正在使用的真实链接有效)。您会注意到我正在使用Grand Central Dispatch,以便我可以更新UI而无需等待解析JSON来完成。

仪器检测到的线条被星号包围。我想帮助那些可能知道这里发生了什么的人。完整的堆栈跟踪(如下面的评论中所述,我将放在这里:)

  

+(NSJSONSerialization JSONObjectWithData:option:error:] - > - [_ NSJSONReader parseData:options:] - > - [_ NSJSONReader parseUTF8JSONData:skipBytes:options] - > newJSONValue-> newJSONString-> [NSPlaceholde RSTRING   initWithBytes:长度:编码:]

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

1 个答案:

答案 0 :(得分:0)

我在使用ARC时就使用了ARC,然后在应用程序中添加了一个应用程序 - 点是你可以切换到ARC。也就是说,我尝试通过创建一个应用了无弧标志的类/文件来重现您的问题,但无法重现该问题。这让我相信你的问题在别的地方。在下面的代码中,我在另一个文件中创建一个Test对象,保留它,并向它发送测试消息。无论我将“i”设置为什么,它总是释放对象:

#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