2016-07-15 1 views
2

Я изо всех сил пытаюсь исправить утечку памяти в вспомогательной функции, которую я создал. Вспомогательная функция принимает результатУтечка памяти при обращении к объекту Foundation из NSJSONSerialization

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

и преобразует все листовые элементы в NSStrings, если они являются NSNumbers.

Вот метод:

-(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-Code указал мне на этот метод как причину моей проблемы.

Instruments showing leaks

Как вы можете видеть, что я попробовал оборачивать вещи в autorelease бассейны, autoreleasing и отпуская. Я просто не вижу здесь никакого выхода.

Это проект не ARC, который работает 24/7.

Редактировать: Я принял совет от 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; 
} 
+0

выглядит как много кода, который может быть заменен на 'mutableCopy'. – Droppy

+0

Я столкнулся с такой же проблемой утечки памяти в массивах. Я добавлял изображения в NSMutableArray. Даже, я удалил все объекты, как вы, он все еще течет. Вы ничего не можете сделать для этого, потому что это зависит от Xcode, чтобы очистить память. Он делает, когда хочет. Но чтобы избежать его последствий, вы можете разделить свой код и запустить некоторые части в основной очереди, а некоторые - в фоновом режиме в зависимости от ваших потребностей. – WasimSafdar

+0

в исходном коде изменения кода NSMutableArray * mutable = [[[NSMutableArray alloc] initWithCapacity: [inputArray count]] autorelease]; и добавить [addDictionary release]; сразу после [mutable addObject: addDictionary]; и возвращать изменяемые; – larva

ответ

1

проблема:

  1. addDictionary называется alloc, но не называют release или autorelease
  2. returnArray = [изменчивый копия]; // было увеличение retainCount +1, нужно autorelease здесь
  3. id theObject = [inputArray[i] objectForKey:keys[j]]; // не требуется автореферат или релиз для объекта, который не принадлежит
  4. add N SAutoreleasePool к началу в нижней части здесь просто ничего не делать

решение:

-(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; 
} 
+0

Спасибо A Báo Я думаю, что это проделало эту работу. Это дает мне проблемы с другим пулом AutoRelease дальше. Я буду работать над этим и отметить это как правильно, когда я его работаю. –

+0

@DavidP Я отредактировал ответ для // не нуждаюсь в автообновлении или выпуске для объекта, который у вас нет. Попробуйте новый код – larva

+0

Спасибо @A Báo, это действительно привело меня на правильный путь. В этой функции есть еще одна утечка. Инструменты X-Code идентифицируют его в методе NSJSONSerialization JSONObjectWithData. Я думаю, что это другой вопрос. –

Смежные вопросы