I'm unable to swap an array of strings on cell reorder:
var scatola : [String] = []
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
swap(&scatola[fromIndexPath.row], &scatola[toIndexPath.row])
}
this code throws:
inout writeback to computed property 'scatola' occurs in multiple arguments to call, introducing invalid aliasing
What is the right way to do it?
An array can be mutable and immutable. In the Swift array, we can swap the position of the elements. To do so we use the swapAt() function.
Alternatively,
let f = fromIndexPath.row, t = toIndexPath.row
(scatola[f], scatola[t]) = (scatola[t], scatola[f])
Update: As of Swift 3.2/4 (Xcode 9) you have to use the swapAt()
method on
the collection
scatola.swapAt(fromIndexPath.row, toIndexPath.row)
because passing the array as two different
inout
arguments to the same function is no longer legal,
compare SE-0173 Add MutableCollection.swapAt(_:_:)
).
Update: I tested the code again with Xcode 6.4, and the problem does not occur anymore. It compiles and runs as expected.
(Old answer:) I assume that scatola
is a stored property in the view controller:
var scatola : [Int] = []
Your problem seems be related to the problem discussed in https://devforums.apple.com/thread/240425. It can already be reproduced with:
class MyClass {
var array = [1, 2, 3]
func foo() {
swap(&array[0], &array[1])
}
}
Compiler output:
error: inout writeback to computed property 'array' occurs in multiple arguments to call, introducing invalid aliasing swap(&array[0], &array[1]) ^~~~~~~~ note: concurrent writeback occurred here swap(&array[0], &array[1]) ^~~~~~~~
I haven't yet grasped the contents of the discussion completely (too late here :), but there is one proposed "workaround", namely to mark the property as final (so that you cannot override it in a subclass):
final var scatola : [Int] = []
Another workaround that I found is to get a pointer on the underlying array storage:
scatola.withUnsafeMutableBufferPointer { (inout ptr:UnsafeMutableBufferPointer<Int>) -> Void in
swap(&ptr[fromIndexPath.row], &ptr[toIndexPath.row])
}
Of course, the fool-proof solution would simply be
let tmp = scatola[fromIndexPath.row]
scatola[fromIndexPath.row] = scatola[toIndexPath.row]
scatola[toIndexPath.row] = tmp
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With