Swift: passa la matrice per riferimento?

Voglio passare il mio chatsViewController.chats Swift chatsViewController.chats a chatsViewController.chats per riferimento (in modo che quando aggiungo una chat a account.chats , chatsViewController.chats punti ancora su account.chats ). Cioè, non voglio che Swift separi i due array quando cambia la durata dell’account.chats.

Le strutture in Swift vengono passate per valore, ma è ansible utilizzare il modificatore inout per modificare l’array (vedere le risposte di seguito). Le classi vengono passate per riferimento. Array e Dictionary in Swift sono implementati come strutture.

Per l’operatore dei parametri di funzione usiamo:

let (è l’operatore predefinito, quindi possiamo omettere let ) per rendere costante un parametro (significa che non possiamo modificare anche la copia locale);

var per renderlo variabile (possiamo modificarlo localmente, ma non influenzerà la variabile esterna che è stata passata alla funzione); e

per renderlo un parametro in-out. In-out significa infatti passare la variabile per riferimento, non per valore. E richiede non solo di accettare valore per riferimento, ma anche di passarlo per riferimento, quindi foo(&myVar) con &foo(&myVar) invece di solo foo(myVar)

Quindi fai così:

 var arr = [1, 2, 3] func addItem(inout localArr: [Int]) { localArr.append(4) } addItem(&arr) println(arr) // it will print [1, 2, 3, 4] 

Per essere precisi non è solo un riferimento, ma un vero alias per la variabile esterna, quindi puoi fare un trucco con qualsiasi tipo di variabile, ad esempio con numero intero (puoi assegnargli un nuovo valore), anche se potrebbe non essere un buona pratica e potrebbe essere fonte di confusione modificare i tipi di dati primitivi come questo.

Definisci te stesso un BoxedArray che implementa l’interfaccia Array ma delega tutte le funzioni a una proprietà memorizzata. Come tale

 class BoxedArray : MutableCollection, Reflectable, ... { var array : Array // ... subscript (index: Int) -> T { get { return array[index] } set(newValue) { array[index] = newValue } } } 

Usa BoxedArray ovunque tu usi una Array . L’assegnazione di un BoxedArray sarà per riferimento, è una class, e quindi le modifiche alla proprietà memorizzata, attraverso l’interfaccia Array , saranno visibili a tutti i riferimenti.

Per le versioni Swift 3-4 (XCode 8-9), utilizzare

 var arr = [1, 2, 3] func addItem(_ localArr: inout [Int]) { localArr.append(4) } addItem(&arr) print(arr) 

Qualcosa di simile a

 var a : Int[] = [] func test(inout b : Int[]) { b += [1,2,3,4,5] } test(&a) println(a) 

???

Un’altra opzione consiste nel chiedere al proprietario dell’array di chiedere al proprietario se necessario. Ad esempio, qualcosa sulla falsariga di:

 class Account { var chats : [String]! var chatsViewController : ChatsViewController! func InitViewController() { chatsViewController.getChats = { return self.chats } } } class ChatsViewController { var getChats: (() -> ([String]))! func doSomethingWithChats() { let chats = getChats() // use it as needed } } 

È quindi ansible modificare la matrice quanto si desidera all’interno della class Account. Si noti che questo non aiuta se si desidera modificare anche l’array dalla class del controller di visualizzazione.

Swift 3 e Xcode 8:

 var myArray = [1, 2, 3] for (index, value) in myArray.enumerated() { // if you don't need the value you could do: for (index, _) in myArray.enumerated() myArray[index].append(4) } 

L’utilizzo di inout è una soluzione, ma non mi sembra molto sfavorevole dato che gli array sono tipi di valore. Stilisticamente personalmente preferisco restituire una copia mutata:

 func doSomething(to arr: [Int]) -> [Int] { var arr = arr arr.append(3) // or likely some more complex operation return arr } var ids = [1, 2] ids = doSomething(to: ids) print(ids) // [1,2,3]