如何在swift中创建不可变数组的可变副本?

时间:2014-07-13 10:09:02

标签: ios arrays 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

6 个答案:

答案 0 :(得分:19)

问题是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)

答案 1 :(得分:13)

数组是值类型(struct),因此它们是按值传递的,而不是通过引用传递的。

也就是说,如果你创建一个数组类型的变量并为它分配不可变数组,那么实际创建并分配不可变数组的副本 - 当然该副本与原始不可变数组没有任何关系(除此之外)在创建时具有相同的值。)

let immutable = [1, 2, 3]

//immutable[0] = 1 // Fails, ok

var mutable = immutable

mutable[0] = 5

在您的情况下,您正在访问NSArray AnyObject的{​​{1}}的不可变数组(请参阅documentation)。你可以在swift中将它用作数组,复制它并修改如下:

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属性

答案 2 :(得分:1)

就像用数组声明var一样简单。

var items = toolbar.items

现在您可以更改项目,然后重新分配到工具栏。

toolbar.items = items

请注意, can 不能(从Beta 3开始)改变用let声明的“不可变”数组的元素。只是数组的长度是是固定的,这就是你不能删除项目的原因。

但是,根据Apple的UIToolbar文档,items数组已经是可变的。

  

SWIFT
  var items: [AnyObject]!

答案 3 :(得分:1)

经过测试+工作:

    var mutable : [UIBarButtonItem] = []
    for button in toolbar.items {
        mutable += button as UIBarButtonItem
    }
    mutable.removeAtIndex(2)
    toolbar.setItems(mutable, animated: true)

答案 4 :(得分:1)

从阵列的特定索引中删除对象。

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)

答案 5 :(得分:0)

在Beta3中,常量数组是完全不可变的,而变量数组是完全可变的。所以只需将let array:更改为var array:然后验证您的代码