Как создать изменяемую копию неизменяемого массива в swift?
Теперь, когда Swift Array действительно неизменяемы благодаря полной семантике значений, как я могу создать изменяемую копию неизменяемого массива? Аналогично Obj-C mutableCopy()
. Я могу, конечно, сжать массив в NSArray и использовать mutableCopy()
, но не хочу использовать NSArray, потому что он не строго типизирован.
У меня есть toolbar
, который имеет items
из раскадровки. Я хочу удалить элемент с панели инструментов и использовать toolbar.setItems
. Я хотел сделать это без кавычки как NSArray
, потому что ни одна из этих функций не принимает NSArrays
, они берут [AnyObject]
.
Очевидно, теперь, когда я вызываю removeAtIndex()
, это не работает, что является правильным. Мне просто нужен mutableCopy
Простое назначение var не работает для меня и дайте 'Immutable value of type [AnyObject]
'
var toolbarItems = self.toolbar.items
toolbarItems.removeAtIndex(2) //Immutable value of type [AnyObject]
Я использую Beta 3
Ответы
Ответ 1
Проблема заключается в том, что self.toolbar.items
является неявно развернутым необязательным (типа [AnyObject]!), и они всегда неизменяемы. Когда вы назначаете переменную toolbarItems
без явного указания ее типа, она также становится неявно разворачиваемой необязательной и, следовательно, также неизменной.
Чтобы исправить это, выполните следующие действия:
var toolbarItems:[AnyObject] = self.toolbar.items
toolbarItems.removeAtIndex(2)
Или:
var toolbarItems = self.toolbar.items as [AnyObject]
toolbarItems.removeAtIndex(2)
Обновление
Как и в Xcode 6 Beta 5, вы можете обновлять коллекции, которые хранятся в необязательных переменных, поэтому исходный код теперь работает:
var toolbarItems = self.toolbar.items
toolbarItems.removeAtIndex(2)
Ответ 2
Массивы - это типы значений (struct), поэтому они передаются по значению, а не по ссылке.
Тем не менее, если вы создаете переменную типа массива и присваиваете ей неизменяемый массив, то копия неизменяемого массива фактически создается и назначается ему - и, конечно, эта копия не имеет отношения к исходному неизменяемому массиву (кроме того, имея те же значения во время создания).
let immutable = [1, 2, 3]
//immutable[0] = 1 // Fails, ok
var mutable = immutable
mutable[0] = 5
В вашем случае вы получаете доступ к неизменяемому массиву, который является NSArray
of AnyObject
(см. documentation). Вы можете использовать его как Массив в быстрой, сделать его копию и изменить следующим образом:
let immutable : NSArray = [ 1, 2, 3 ]
//immutable[0] = 1 // Fails, ok
var mutable : [AnyObject] = immutable
mutable.removeAtIndex(1) // mutable now is [1, 3]
mutable[0] = 7 // mutable now is [7, 3]
После того, как вы закончите с изменениями, вы можете назначить свойству items
Ответ 3
Это так же просто, как объявление var
с вашим массивом.
var items = toolbar.items
Теперь вы можете изменять элементы, а затем переназначать на панель инструментов.
toolbar.items = items
Обратите внимание, что вы can не можете (начиная с Beta 3) изменять элементы "неизменяемого" массива, объявленного с помощью let
. Исправлена длина массива , поэтому вы не можете удалить элементы.
Однако, согласно документации Apple UIToolbar
, массив items
уже изменен.
СВИФТ
var items: [AnyObject]!
Ответ 4
Протестировано + работает:
var mutable : [UIBarButtonItem] = []
for button in toolbar.items {
mutable += button as UIBarButtonItem
}
mutable.removeAtIndex(2)
toolbar.setItems(mutable, animated: true)
Ответ 5
ИЗМЕНИТЬ ОБЪЕКТ ИЗ ОПРЕДЕЛЕННОГО ИНДЕКСА МАССЫ.
let fullArray : NSArray = Userdefaults().value(forKey: "YOUR_ARRAY_STRING") as! NSArray
var mutableArray : [AnyObject] = fullArray as [AnyObject]
mutableArray.remove(at: INDEX_TO_REMOVE) //Eg: mutableArray.remove(at: 0)
mutableArray.append(ARRAY_TO_APPEND)
Ответ 6
В Beta3 постоянные массивы полностью неизменяемы, а переменные массивы полностью изменяемы. Так что просто измените let array: на var array: а затем проверьте свой код