Swift交换数组对象

12

我无法在单元格重新排序时交换字符串数组:

var scatola : [String] = []

override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
    swap(&scatola[fromIndexPath.row], &scatola[toIndexPath.row])
}

这段代码会抛出以下错误:

在调用时,对计算属性“scatola”进行的输入输出写回出现在多个参数中,引入了无效的别名

该如何正确处理呢?


2
请展示 scatola 的声明。 - rob mayoff
变量 scatola: [String] = [] - Enlil
3个回答

17
更新:Swift 3.2/4(Xcode 9)开始,您必须在集合上使用swapAt()方法。
 scatola.swapAt(fromIndexPath.row, toIndexPath.row)

因为将数组作为两个不同的inout参数传递给同一个函数现在已经不再合法,请比较SE-0173 添加MutableCollection.swapAt(_:_:)


更新:我使用 Xcode 6.4 再次测试了该代码,问题已经不存在了。 它可以按预期编译和运行。


(旧回答:) 我假设 scatola 是视图控制器中的存储属性:

var scatola : [Int] = []

您的问题似乎与 https://devforums.apple.com/thread/240425 中讨论的问题有关。这个问题已经能够被复制:

class MyClass {
    var array = [1, 2, 3]

    func foo() {
        swap(&array[0], &array[1])
    }
}

编译器输出:

错误:在多个参数中调用计算属性 'array' 的 inout 写回出现,引入了无效的别名
        swap(&array[0], &array[1])
                         ^~~~~~~~
注意:并发写回发生在这里
        swap(&array[0], &array[1])
              ^~~~~~~~

我还没有完全掌握讨论的内容(这里太晚了:), 但是有一个提出的“解决方法”,即将该属性标记为 final(以便在子类中无法覆盖它):

final var scatola : [Int] = []

我发现的另一个解决方法是获取底层数组存储的指针:

scatola.withUnsafeMutableBufferPointer { (inout ptr:UnsafeMutableBufferPointer<Int>) -> Void in
    swap(&ptr[fromIndexPath.row], &ptr[toIndexPath.row])
}

当然,万无一失的解决方案就是

let tmp = scatola[fromIndexPath.row]
scatola[fromIndexPath.row] = scatola[toIndexPath.row]
scatola[toIndexPath.row] = tmp

1
在 Swift 3.2 及以上版本中,您需要编写 swapAt(0, 1) - Cœur

16

或者说,

let f = fromIndexPath.row, t = toIndexPath.row
(scatola[f], scatola[t]) = (scatola[t], scatola[f])

很棒且简洁的解决方案,点赞+1。 - Alexandre G.
1
它比交换更安全,因为如果索引相同,则交换会崩溃。虽然此示例中不会发生,但通常在使用交换之前必须检查索引。+1 - Darko
1
这也适用于对象数组。但是,交换不适用于对象数组,它最终会将两个索引替换为相同的对象。 - Luke

0

从Xcode 9开始,你可以这样写:

@objc override func tableView(_ tableView: UITableView, 
                moveRowAt sourceIndexPath: IndexPath, 
                  to destinationIndexPath: IndexPath) {
    scatola.swapAt(sourceIndexPath.row, destinationIndexPath.row)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接