Как конвертировать NSMutableArray в NSArray в Objective-C?
NSArray *array = mutableArray;
Как конвертировать NSMutableArray в NSArray в Objective-C?
NSArray *array = mutableArray;
Ответы:
NSArray *array = [mutableArray copy];
Copy
делает неизменные копии. Это очень полезно, потому что Apple может делать различные оптимизации. Например, отправка copy
в неизменяемый массив только сохраняет объект и возвращает self
.
Если вы не используете сборщик мусора или ARC, помните, что -copy
сохраняет объект.
copy
хорош , но как я могу узнать из документов, которые создают обычный NSArray, а не NSMutableArray?
NSArray
& NSMutableArray
, NSString
& NSMutableString
. Но не например, NSViewController
который всегда содержит изменяемое состояние.
An NSMutableArray
является подклассом, NSArray
так что вам не всегда нужно конвертировать, но если вы хотите убедиться, что массив не может быть изменен, вы можете создать NSArray
любой из этих способов в зависимости от того, хотите ли вы, чтобы он был автоматически освобожден или нет:
/* Not autoreleased */
NSArray *array = [[NSArray alloc] initWithArray:mutableArray];
/* Autoreleased array */
NSArray *array = [NSArray arrayWithArray:mutableArray];
РЕДАКТИРОВАТЬ: Решение, предоставленное Георгом Schölly, является лучшим способом сделать это и намного чище, особенно теперь, когда у нас есть ARC и даже не нужно вызывать autorelease.
Мне нравятся оба основных решения:
NSArray *array = [NSArray arrayWithArray:mutableArray];
Или
NSArray *array = [mutableArray copy];
Основное различие я вижу в них , как они ведут себя , когда mutableArray равна нулю :
NSMutableArray *mutableArray = nil;
NSArray *array = [NSArray arrayWithArray:mutableArray];
// array == @[] (empty array)
NSMutableArray *mutableArray = nil;
NSArray *array = [mutableArray copy];
// array == nil
[mutableArray copy]
его можно упростить до [nil copy]
. В target-c любое сообщение, отправленное на ноль, всегда будет ноль. Важно помнить различие между «ничем» и «массивом, в котором ничего нет».
вы попробуйте этот код ---
NSMutableArray *myMutableArray = [myArray mutableCopy];
а также
NSArray *myArray = [myMutableArray copy];
Ниже приведен способ преобразования NSMutableArray в NSArray:
//oldArray is having NSMutableArray data-type.
//Using Init with Array method.
NSArray *newArray1 = [[NSArray alloc]initWithArray:oldArray];
//Make copy of array
NSArray *newArray2 = [oldArray copy];
//Make mutablecopy of array
NSArray *newArray3 = [oldArray mutableCopy];
//Directly stored NSMutableArray to NSArray.
NSArray *newArray4 = oldArray;
В Swift 3.0 появился новый тип данных Array . Объявите массив с помощью let
ключевого слова, тогда он станет NSArray. А если объявите с помощью var
ключевого слова, то он станет NSMutableArray .
Образец кода:
let newArray = oldArray as Array
В объективе-c:
NSArray *myArray = [myMutableArray copy];
В скором времени:
var arr = myMutableArray as NSArray
NSArray *array = mutableArray;
Этот [mutableArray copy]
антипаттерн есть во всем примере кода. Прекратите делать это для одноразовых изменяемых массивов, которые являются временными и освобождаются в конце текущей области.
Нет способа, которым среда выполнения могла бы оптимизировать бесполезное копирование изменяемого массива, который вот-вот выйдет из области видимости, уменьшится до 0 и будет освобожден навсегда.
NSMutableArray
к NSArray
переменной не тайному его (что вопрос в OP составляет около). Предоставление такого значения (например, в качестве возвращаемого значения или в качестве свойства) может привести к очень сложным проблемам отладки, если это значение было неожиданно изменено. Это относится как к внутренним, так и к внешним мутациям, поскольку изменяемое значение является общим.
NSMutableArray
переменной. Поскольку объект никогда не переставал быть изменяемым массивом, вызов методов с мутацией для него завершится успешно и приведет к изменению общих данных. Если, с другой стороны, исходный изменяемый массив был скопирован, изменив его на неизменяемый массив, а затем назначен NSMutableArray
переменной и вызвав методы мутации, эти вызовы завершатся ошибкой, doesNotRespondToSelector
поскольку объект, получивший вызов метода мутации, находится в факт неизменен и не отвечает на эти методы.
Если вы создаете массив с помощью изменчивости, а затем хотите вернуть неизменяемую версию, вы можете просто вернуть изменяемый массив как «NSArray» через наследование.
- (NSArray *)arrayOfStrings {
NSMutableArray *mutableArray = [NSMutableArray array];
mutableArray[0] = @"foo";
mutableArray[1] = @"bar";
return mutableArray;
}
Если вы «доверяете» вызывающей стороне для обработки (технически все еще изменяемого) возвращаемого объекта как неизменяемого NSArray, это более дешевый вариант, чем [mutableArray copy]
.
Чтобы определить, может ли он изменить полученный объект, получатель сообщения должен полагаться на формальный тип возвращаемого значения. Если он получает, например, объект массива, типизированный как неизменяемый, он не должен пытаться изменить его . Неприемлемой практикой программирования является определение того, является ли объект изменчивым, основываясь на его принадлежности к классу.
Вышеуказанная практика обсуждается более подробно здесь:
NSArray *array = [mutableArray copy];