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?
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
Alternatively,
let f = fromIndexPath.row, t = toIndexPath.row
(scatola[f], scatola[t]) = (scatola[t], scatola[f])
Starting Xcode 9, you can write:
@objc override func tableView(_ tableView: UITableView,
moveRowAt sourceIndexPath: IndexPath,
to destinationIndexPath: IndexPath) {
scatola.swapAt(sourceIndexPath.row, destinationIndexPath.row)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.