Объекты массива Swift swap

Я не могу поменять массив строк на ячейку reorder

var scatola : [String] = []

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

этот код бросает: обратная запись inout в вычисляемое свойство "scatola" происходит в нескольких аргументах для вызова, вводя недопустимое сглаживание

Как правильно это сделать?

3 ответов


обновление: по состоянию на 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])
    }
}

компилятор выход:

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])
              ^~~~~~~~

Я еще не понял содержание обсуждения полностью (слишком поздно здесь :), но есть один предложенный "обходной путь", а именно пометить свойство как окончательное (чтобы вы не могли его переопределить в подклассе):

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

кроме того,

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

запуск Xcode 9, вы можете написать:

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