Есть ли встроенная функция, которая позволяет мне глубоко копировать NSMutableArray
?
Я огляделся, некоторые говорят, что [aMutableArray copyWithZone:nil]
работает как глубокая копия. Но попробовал и вроде неглубокая копия.
Прямо сейчас я вручную делаю копию с помощью for
цикла:
//deep copy a 9*9 mutable array to a passed-in reference array
-deepMuCopy : (NSMutableArray*) array
toNewArray : (NSMutableArray*) arrayNew {
[arrayNew removeAllObjects];//ensure it's clean
for (int y = 0; y<9; y++) {
[arrayNew addObject:[NSMutableArray new]];
for (int x = 0; x<9; x++) {
[[arrayNew objectAtIndex:y] addObject:[NSMutableArray new]];
NSMutableArray *aDomain = [[array objectAtIndex:y] objectAtIndex:x];
for (int i = 0; i<[aDomain count]; i++) {
//copy object by object
NSNumber* n = [NSNumber numberWithInt:[[aDomain objectAtIndex:i] intValue]];
[[[arrayNew objectAtIndex:y] objectAtIndex:x] addObject:n];
}
}
}
}
но мне хотелось бы более четкое и емкое решение.
objective-c
cocoa-touch
cocoa
nsarray
deep-copy
ivanTheTerrible
источник
источник
-copy
неизменяемых коллекций изменилось между Mac OS X 10.4 и 10.5: developer.apple.com/library/mac/releasenotes/Cocoa/… (прокрутите вниз до «Неизменяемые коллекции и поведение копирования»)copy
, что нужно поместить в «глубокую копию»? Если элемент является другой коллекцией,copy
фактически не дает копии (того же класса). Так что я думаю, что совершенно справедливо спорить о типе копии, которая требуется в конкретном случае.NSCopying
/-copy
, то он не может быть скопирован - поэтому вам никогда не следует пытаться сделать его копию, потому что это не та возможность, для которой он был разработан. С точки зрения реализации Какао, некопируемые объекты часто имеют какое-то внутреннее состояние C, к которому они привязаны, поэтому взлом прямой копии объекта может привести к состоянию гонки или хуже. Итак, чтобы ответить «что поместить в« глубокую копию »» - оставлено исх. Единственное, что можно положить куда угодно, когда у вас есть неNSCopying
объект.Ответы:
В документации Apple о глубоких копиях прямо говорится:
Приведенный выше код создает новый массив, члены которого являются неглубокими копиями членов старого массива.
Обратите внимание, что если вам нужно глубоко скопировать всю вложенную структуру данных - то, что связанные документы Apple называют настоящей глубокой копией - этого подхода будет недостаточно. Пожалуйста, посмотрите другие ответы здесь.
источник
copyWithZone:
реализовано в принимающем классе.Единственный известный мне способ легко сделать это - заархивировать, а затем немедленно разархивировать ваш массив. Это похоже на взлом, но на самом деле это явно предлагается в документации Apple по копированию коллекций , в которой говорится:
Загвоздка в том, что ваш объект должен поддерживать интерфейс NSCoding, поскольку он будет использоваться для хранения / загрузки данных.
Версия Swift 2:
источник
initWithArray:copyItems:
методе? Этот обходной путь архивирования / разархивирования кажется очень полезным, учитывая, сколько классов управления соответствуют NSCoding, но не NSCopying.Копировать по умолчанию дает неглубокую копию
Это потому, что вызов
copy
- это то же самое, чтоcopyWithZone:NULL
и копирование с зоной по умолчанию.copy
Вызов не приводит к глубокой копии. В большинстве случаев это даст вам неглубокую копию, но в любом случае это зависит от класса. Для подробного обсуждения я рекомендую темы программирования коллекций на сайте разработчиков Apple.initWithArray: CopyItems: дает одноуровневую глубокую копию
NSCoding
это рекомендуемый Apple способ предоставить полную копиюДля истинной глубокой копии (массива массивов) вам потребуется
NSCoding
заархивировать / разархивировать объект:источник
Для словаря
NSMutableDictionary *newCopyDict = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)objDict, kCFPropertyListMutableContainers);
Для массива
NSMutableArray *myMutableArray = (NSMutableArray *)CFPropertyListCreateDeepCopy(NULL, arrData, kCFPropertyListMutableContainersAndLeaves);
источник
Нет, в фреймворки для этого ничего не встроено. Коллекции какао поддерживают мелкие копии (с помощью методов
copy
илиarrayWithArray:
), но даже не говорят о концепции глубокого копирования.Это связано с тем, что «глубокую копию» становится трудно определить по мере того, как содержимое ваших коллекций начинает включать ваши собственные настраиваемые объекты. Означает ли «глубокая копия», что каждый объект в графе объектов является уникальной ссылкой относительно каждого объекта в исходном графе объектов?
Если бы существовал какой-то гипотетический
NSDeepCopying
протокол, вы могли бы настроить его и принимать решения во всех своих объектах, но, к сожалению, его нет. Если бы вы контролировали большинство объектов на своем графике, вы могли бы создать этот протокол самостоятельно и реализовать его, но вам нужно будет добавить категорию в классы Foundation по мере необходимости.Ответ @ AndrewGrant, предполагающий использование архивирования / разархивирования с ключом, является неэффективным, но правильным и чистым способом достижения этого для произвольных объектов. Эта книга даже заходит так далеко, что предлагает добавить категорию ко всем объектам, которые делают именно это, для поддержки глубокого копирования.
источник
У меня есть обходной путь, если я пытаюсь получить глубокую копию для данных, совместимых с JSON.
Просто возьмите
NSData
вNSArray
использовании ,NSJSONSerialization
а затем воссоздать JSON объект, это создаст совершенно новую и свежую копиюNSArray/NSDictionary
с новыми ссылками и память о них.Но убедитесь, что объекты NSArray / NSDictionary и их дочерние элементы должны быть сериализуемыми в формате JSON.
источник
NSJSONReadingMutableContainers
этом вопросе вы должны указать вариант использования.