从NSJSONSerialization处理Foundation对象时内存泄漏

时间:2016-07-15 07:27:51

标签: objective-c xcode cocoa memory-leaks nsjsonserialization

我正在努力修复我所做的辅助函数中的内存泄漏。辅助函数采用

的结果
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError * _Nullable *)error 

并将所有叶元素转换为NSStrings(如果它们是NSNumber)。

以下是方法:

-(NSArray *) stringisizeObjects:(NSArray *)inputArray{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSMutableArray *mutable = [[NSMutableArray alloc] initWithCapacity:[inputArray count]];

    for (int i = 0; i < [inputArray count]; i++) {
        NSArray *keys = [inputArray[i] allKeys];

        NSMutableDictionary *addDictionary = [[NSMutableDictionary alloc] initWithCapacity:[keys count]];

        for (int j = 0; j < [keys count]; j++) {

            id theObject = [[inputArray[i] objectForKey:keys[j]]autorelease];

            if ([theObject isKindOfClass:[NSNumber class]]) {

                [addDictionary setObject:[theObject stringValue] forKey:keys[j]];
                [theObject release];

            }else if ([theObject isKindOfClass:[NSString class]]){
                [addDictionary setObject:[inputArray[i] objectForKey:keys[j]] forKey:keys[j]];
            }

        }
        [mutable addObject:addDictionary];
    }
    NSArray *returnArray = [mutable copy];

    [mutable removeAllObjects];
    [mutable release];
    [pool drain];
    return returnArray;
}

以下是我获取输入数组的方法。

id parsedThingy = [NSJSONSerialization JSONObjectWithData:resultJSONData options:1 error:&jsonDecodeError];

在我将结果传递给我的stringisize方法之前,我必须确保我有一个带有匹配键的NSDrary NSArray。

NSArray *resultArray = [self stringisizeObjects:parsedThingy];

X-Code内存泄漏工具指出我这个方法是我问题的原因。

Instruments showing leaks

正如您所看到的,我已尝试将内容包装在自动释放池中,自动释放和释放。我只是没有看到前进的方向。

这是一个全天候运行的非ARC项目。

编辑:我接受了Droppy的建议并尝试使用mutableCopy重新编写该方法。泄漏仍在那里。在这一点上,我唯一的工作可能是改变JSON的源只发送字符串。 :(

-(NSArray *) stringisizeObjects2:(NSArray *)inputArray{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSMutableArray *mutableArray = [inputArray mutableCopy];

    for (int i = 0; i < [mutableArray count]; i++) {
        NSMutableDictionary *mutableDict = [mutableArray[i] mutableCopy];
        NSArray *keys = [mutableDict allKeys];

        for (int j = 0; j < [keys count]; j++) {
            if ([[mutableDict objectForKey:keys[j]] isKindOfClass:[NSNumber class]]) {
                NSString *stringValue = [[mutableDict objectForKey:keys[j]] stringValue];

                [mutableDict removeObjectForKey:keys[j]];
                [mutableDict setObject:stringValue  forKey:keys[j]];
            }
        }
        mutableArray[i] = [mutableDict copy];
        [mutableDict release];
    }

    NSArray *returnArray = [mutableArray copy];

    [mutableArray release];
    [pool drain];
    return returnArray;
}

1 个答案:

答案 0 :(得分:1)

问题:

  1. addDictionary致电alloc但未致电releaseautorelease
  2. returnArray = [mutable copy]; //确实增加了retainCount +1,这里需要autorelease
  3. id theObject = [inputArray[i] objectForKey:keys[j]]; //不需要自动释放或释放您不拥有的对象
  4. 在这里添加NSAutoreleasePool到顶部,什么都不做
  5. 溶液:

    -(NSArray *) stringisizeObjects:(NSArray *)inputArray{
        NSMutableArray *mutable = [[NSMutableArray alloc] initWithCapacity:[inputArray count]];
    
        for (int i = 0; i < [inputArray count]; i++) {
            NSArray *keys = [inputArray[i] allKeys];
    
            NSMutableDictionary *addDictionary = [[NSMutableDictionary alloc] initWithCapacity:[keys count]];
    
            for (int j = 0; j < [keys count]; j++) {
    
                id theObject = [inputArray[i] objectForKey:keys[j]]; // not need autorelease
    
                if ([theObject isKindOfClass:[NSNumber class]]) {
    
                    [addDictionary setObject:[theObject stringValue] forKey:keys[j]];
                    //[theObject release]; // not need release value here
    
                }else if ([theObject isKindOfClass:[NSString class]]){
                    [addDictionary setObject:[inputArray[i] objectForKey:keys[j]] forKey:keys[j]];
                }
    
            }
            [mutable addObject:addDictionary];
            [addDictionary release]; // release after not use
        }
        NSArray *returnArray = [[[NSArray alloc] initWithArray:mutable] autorelease]; // auto release for return value
    
        [mutable removeAllObjects];
        [mutable release];
        return returnArray;
    }