Утечка памяти при обработке объекта Foundation из NSJSONSerialization
Я изо всех сил пытаюсь исправить утечку памяти в вспомогательной функции, которую я сделал. Вспомогательная функция принимает результат
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError * _Nullable *)error
И преобразует все листовые элементы в NSStrings, если они являются NSN-номерами.
Вот метод:
-(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, я должен убедиться, что у меня есть NSArray NSDictionaries с соответствующими ключами.
NSArray *resultArray = [self stringisizeObjects:parsedThingy];
Инструмент утечки памяти X-кода имеет указал мне на этот метод как на причину моей проблемы.
Как вы можете видеть, я пробовал упаковывать вещи в пулы авторелиза, авторелиза и выпуска. Я просто не вижу никакого пути вперед.Это не ARC проект, который работает 24/7.
Edit: я воспользовался советом 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 ответ:
Задача:
addDictionary
вызываетсяalloc
, но не вызываетrelease
илиautorelease
- returnArray = [изменяемая копия]; / / did increase retainCount +1, need
autorelease
hereid theObject = [inputArray[i] objectForKey:keys[j]];
/ / не нужен авторелиз или релиз для объекта, которым вы не владеете- добавьте NSAutoreleasePool сверху и снизу здесь просто ничего не делайте
Решение:
-(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; }