2014-10-10 15 views
10

jestem w stanie zamienić tablicę łańcuchów na komórkę ReorderSwift tablica zamiana obiektów

var scatola : [String] = [] 

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

ten kod rzuca: inout opóźnionego zapisu do obliczonej własności „Scatola” występuje w wielu argumentów do rozmowy, wprowadzając nieprawidłowy aliasing

jaki jest właściwy sposób na zrobienie tego?

+2

Pokaż nam deklarację 'scatola'. –

+0

var scatola: [String] = [] – Enlil

Odpowiedz

16

Update: Na Swift 3,2/4 (Xcode 9) trzeba użyć metody swapAt() na Kolekcji

scatola.swapAt(fromIndexPath.row, toIndexPath.row) 

ponieważ przepuszczanie tablicy jako dwa różne inout argumentów do ta sama funkcja nie jest już legalna, porównaj SE-0173 Add MutableCollection.swapAt(_:_:)).


Aktualizacja: Przetestowałem kod ponownie Xcode 6.4, a problem nie występuje już. Kompiluje się i działa zgodnie z oczekiwaniami.


(Old odpowiedź :) Zakładam, że scatola jest przechowywany nieruchomość w kontrolerze widoku:

var scatola : [Int] = [] 

Twój problem wydaje się być związane z problemem omawianym w https://devforums.apple.com/thread/240425. To może już być powielana z: wyjściem

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

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

Compiler:

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

jeszcze nie chwycił zawartość dyskusji całkowicie (zbyt późno tutaj :), ale jest jeden zaproponował „obejście”, a mianowicie, aby zaznaczyć obiekt jako końcowy (tak, że nie można zastąpić go w podklasy):

final var scatola : [Int] = [] 

Innym obejście, które znalazłem jest, aby wskaźnik na podstawowej przechowywania tablicy:

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

Oczywiście, rozwiązanie idiotoodporny byłoby po prostu

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

w Swift 3.2 i wyżej, musisz napisać 'swapAt (0, 1)'. –

15

Alternatywnie

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

Ładne rozwiązanie!+1 – ZYiOS

+0

Świetne i zwięzłe rozwiązanie, +1 –

+1

I jest bezpieczniejsze niż zamiana, ponieważ zamiana ulega awarii, jeśli indeksy są takie same. Nie może się zdarzyć w tym przykładzie, ale zazwyczaj indeksy muszą zostać sprawdzone przed użyciem zamiany. +1 – Darko

0

Zaczynając od Xcode 9, możesz napisać:

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