2014-02-11 3 views
10

При возврате NSArray (или NSDictionary и т. Д.) Из метода, который строит массив «на лету» с использованием NSMutableArray, что является стандартным способом для этого и избегать случайных утечки памяти при использовании ARC?Возврат объекта NSMutableArray из метода с возвращаемым значением NSArray

Например, предположим, что мы имели некоторый класс со списком имен, и мы хотели, чтобы вручную фильтровать и захватить все имена, которые начали с данной буквы:

- (NSArray *)getNamesByFirstLetter:(NSString *)firstLetter 
{ 
    NSMutableArray *returnValue = [[NSMutableArray alloc] init]; 
    for(id item in self.names) 
    { 
     if([item hasPrefix:firstLetter]) 
     { 
      [returnValue addObject:item]; 
     } 
    }   
    return returnValue; // just return the above array 
} 

Когда речь идет о возвращении значение, я могу думать о четырех возможных способов сделать это:

  1. Верните NSMutableArray непосредственно (как описано выше)

    return returnValue; 
    
  2. Вернуть copy

    return [returnValue copy]; 
    
  3. NSArray arrayWithArray Возвращение с помощью:

    return [NSArray arrayWithArray:returnValue]; 
    
  4. NSArray Создать вручную установить NSMutableArray в nil на:

    NSArray *temp = [NSArray arrayWithArray:returnValue]; // could use [returnValue copy] here too 
    returnValue = nil; 
    return temp; 
    

Когда программа использует ARC, существует ли какая-либо реальная разница между этими четырьмя методами или она просто сводится к личным предпочтениям?

Кроме того, помимо возможных утечек памяти, есть ли какие-либо другие последствия при использовании одного метода над другим?

Обратите внимание, что если это дубликат, дайте мне знать, и я отвечу на вопрос. Я попытался выполнить поиск, но с трудом пытался свести проблему до нескольких поисковых запросов.

+3

Не вдаваясь в подробности, ни одна из них не приведет к утечке памяти при включенной ARC. Я должен упомянуть, что 4 и 3 эквивалентны в среде ARC. – Jack

ответ

9

Все четыре ваших варианта в порядке с ARC-поддержкой (т. Е. Ни одно из предлагаемых вами решений не вызовет утечку памяти).

Однако 4 решения, которые вы наметили, делают несколько разные вещи.Номер 1 вернет NSMutableArray, что, вероятно, не вызовет проблем, так как NSMutableArray ответит на все те же сообщения, что и NSArray (но возвращаемый объект будет изменен, что вам может и не понадобиться).

Существует незначительная разница между вариантом 2 и вариантами 3 & 4 (которые идентичны по ARC). Если returnValue - nil, вариант 2 вернет nil, но варианты 3 & 4 вернет пустой NSArray. (Любое поведение может быть желательно, вы должны решить, как вы хотите, чтобы этот метод вел себя). Кроме того, -copy скорее всего работает быстрее, чем +arrayWithArray.

Я бы с вариантом 2.

+0

Имеет смысл. Я просто привык к работе с сборкой мусора, я думаю, что я немного параноик. Кроме того, дальнейшие исследования привели меня к [этому вопросу] (http://stackoverflow.com/questions/14849570) и [этот вопрос] (http://stackoverflow.com/questions/1391914), в которых говорится, что 'arrayWithArray' явно задано авторекламой, в то время как 'copy' не обязательно. Можно ли предположить, что эта разница имеет значение только в программах, не использующих ARC? – valverij

+0

@valverij В средах, собранных для мусора, также не нужно (или даже желательно) устанавливать переменные в «null». Кроме того, ARC скрывает разницу между автореализацией и простым освобождением от программистов, поэтому безопасно игнорировать эту конкретную разницу в вашем случае при компиляции с ARC. – dasblinkenlight

+0

@dasblinkenlight, я знаю, что среда сбора мусора не требует, чтобы вы явно задавали переменные «null», поэтому я беспокоился о том, что что-то не хватает с Objective-C. Спасибо, однако, хорошо знать, что ARC имеет все это. – valverij

3

Прежде всего: ни один из подходов, которые вы обсуждаете, не приведет к утечке памяти под ARC. Кроме того, подход номер четыре не требует от вас установить returnValue на nil - компилятор достаточно умен, чтобы заботиться о returnValue самостоятельно. Это делает подход номер четыре точно таким же, как номер три.

Кроме того, вызов copy на returnValue аналогичен созданию нового массива из его содержимого, поэтому второй подход совпадает с последним.

Это оставляет нам два подхода - первый, а второй/третий/четвертый. Основные различия между ними в том, что пользователь сможет сделать с массивом, который он получает от вашего метода. Первый подход позволяет пользователю изменять массив; последние три - нет. Решение о том, какое поведение вы предпочитаете, зависит от вас.

+1

Неверно, номер 2 предоставил 'NSArray', а не' NSMutableArray', потому что 'copy' был вызван, а не' mutableCopy'. – Gavin

+0

Итак, по существу 2, 3 и 4, все в основном одинаковы. – Gavin

+0

@Gavin Это исправлено, спасибо! – dasblinkenlight

0

Одна вещь, кроме того, что нет утечки в данном примере, является то, что все знают, что NSArray может быть изменяемым. Если вы получите его в результате вызова метода, зависит от вас, скопируете ли вы его или используете как есть, будучи готовым к его изменению в любое время. Вот почему неизменяемые свойства часто объявляются как скопированные, а не сильные. Присвоение изменчивого значения этому свойству будет выполнять реальную копию, а присвоение неизменяемого значения будет дешевым.

tl; dr: just return returnValue, это нормально.

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