Возврат объекта NSMutableArray из метода с возвращаемым значением NSArray
При возврате NSArray
(или NSDictionary
и т.д.) из метода, который строит массив "на лету" с помощью NSMutableArray
, что является стандартным способом для этого и избегать случайных утечек памяти при использовании ARC
Например, скажем, у нас был класс со списком имен, и мы хотели вручную отфильтровать и захватить все имена, которые начинались с данной буквы:
- (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
}
Когда дело доходит до возврата значения, я могу представить четыре возможных способа сделать это:
-
Верните NSMutableArray
напрямую (как указано выше)
return returnValue;
-
Верните a copy
return [returnValue copy];
-
Возврат с помощью NSArray arrayWithArray
:
return [NSArray arrayWithArray:returnValue];
-
Создайте NSArray
, вручную установите NSMutableArray
в nil
:
NSArray *temp = [NSArray arrayWithArray:returnValue]; // could use [returnValue copy] here too
returnValue = nil;
return temp;
Когда программа использует ARC, существует ли какая-либо реальная разница между этими четырьмя методами или она просто сводится к личным предпочтениям?
Кроме того, помимо возможных утечек памяти, есть ли какие-либо другие последствия при использовании одного метода над другим?
Заметьте, если это дубликат, дайте мне знать, и я отвечу на вопрос. Я попытался выполнить поиск, но с трудом пытался свести проблему до нескольких поисковых запросов.
Ответы
Ответ 1
Все четыре из ваших вариантов в порядке с поддержкой ARC (т.е. ни одно из предложенных решений не приведет к утечке памяти).
Однако 4 решения, которые вы наметили, делают несколько разные вещи. Номер 1 вернет NSMutableArray
, который, вероятно, не вызовет проблем, потому что NSMutableArray
будет отвечать на все те же сообщения, что и NSArray
(но возвращенный объект будет изменен, что вам может и не понадобиться).
Существует тонкая разница между опцией 2 и вариантами 3 и 4 (которые идентичны при ARC). Если returnValue
- nil
, опция 2 вернет nil
, но опции 3 и 4 вернут пустой NSArray
. (Любое поведение может быть желательно, вы должны решить, как вы хотите, чтобы этот метод вел себя). Кроме того, -copy
скорее всего работает быстрее, чем +arrayWithArray
.
Я бы выбрал вариант 2.
Ответ 2
Прежде всего: ни один из подходов, которые вы обсуждаете, не приведет к утечке памяти под ARC. Кроме того, подход номер четыре не требует, чтобы вы установили returnValue
в nil
- компилятор достаточно умен, чтобы самостоятельно позаботиться о returnValue
. Это делает подход номер четыре точно таким же, как номер три.
Кроме того, вызов copy
on returnValue
аналогичен созданию нового массива из его содержимого, поэтому второй подход совпадает с вторым.
Это оставляет нам два подхода - первый, второй и третий/четвертый. Основные различия между ними в том, что пользователь сможет сделать с массивом, который он получает от вашего метода. Первый подход позволяет пользователю изменять массив; последние три - нет. Решение о том, какое поведение вы предпочитаете, зависит от вас.
Ответ 3
С одной стороны, в данном примере нет утечек, заключается в том, что все знают, что NSArray может быть изменчивым. Если вы получите его в результате вызова метода, зависит от вас, скопируете ли вы его или используете как есть, будучи готовым к его изменению в любое время. Вот почему неизменяемые свойства часто объявляются как скопированные, а не сильные. Присвоение изменяемого значения этому свойству будет выполнять реальную копию, а присвоение неизменяемого значения будет дешевым.
tl; dr: просто верните returnValue, это нормально.