Odpowiedzi:
Struktury w Swift są przekazywane według wartości, ale możesz użyć inout
modyfikatora, aby zmodyfikować swoją tablicę (patrz odpowiedzi poniżej). Klasy są przekazywane przez referencje. Array
aw Dictionary
Swift są implementowane jako struktury.
NSArray
ponieważ NSArray
tablica Swift ma subtelne różnice semantyczne (takie jak typ referencyjny), co może prowadzić do większej liczby błędów.
inout
ze Structs?
Dla operatora parametru funkcji używamy:
let (jest to domyślny operator, więc możemy pominąć let ), aby uczynić parametr stałym (oznacza to, że nie możemy modyfikować nawet lokalnej kopii);
var, aby uczynić go zmiennym (możemy go modyfikować lokalnie, ale nie wpłynie to na zmienną zewnętrzną, która została przekazana do funkcji); i
inout, aby był to parametr in-out. In-out oznacza w rzeczywistości przekazywanie zmiennej przez odniesienie, a nie przez wartość. Wymaga nie tylko akceptowania wartości przez odniesienie, ale także przekazywania jej przez referencję, więc przekazuj ją za pomocą & - foo(&myVar)
zamiast po prostufoo(myVar)
Więc zrób to tak:
var arr = [1, 2, 3]
func addItem(inout localArr: [Int]) {
localArr.append(4)
}
addItem(&arr)
println(arr) // it will print [1, 2, 3, 4]
Dokładnie to nie jest tylko odniesienie, ale prawdziwy alias dla zmiennej zewnętrznej, więc możesz zrobić taką sztuczkę z dowolnym typem zmiennej, na przykład z liczbą całkowitą (możesz przypisać jej nową wartość), chociaż może to nie być dobrą praktyką i modyfikowanie takich pierwotnych typów danych może być mylące.
inout
pozycja uległa zmianie, czylifunc addItem(localArr: inout [Int])
var
nie jest już dostępny dla atrybutu parametru funkcji.
Zdefiniuj siebie a, BoxedArray<T>
który implementuje Array
interfejs, ale deleguje wszystkie funkcje do przechowywanej właściwości. Takie jak
class BoxedArray<T> : MutableCollection, Reflectable, ... {
var array : Array<T>
// ...
subscript (index: Int) -> T {
get { return array[index] }
set(newValue) { array[index] = newValue }
}
}
Użyj BoxedArray
dowolnego miejsca, w którym chcesz użyć Array
. Przypisanie BoxedArray
woli będzie przez odniesienie, jest to klasa, a tym samym zmiany w przechowywanej właściwości, poprzez Array
interfejs, będą widoczne dla wszystkich referencji.
String
jest podtypem Any
ALE, jeśli import Foundation
następnie String
stajesz się podtypem AnyObject
.
W przypadku wersji Swift 3-4 (XCode 8-9) użyj
var arr = [1, 2, 3]
func addItem(_ localArr: inout [Int]) {
localArr.append(4)
}
addItem(&arr)
print(arr)
Coś jak
var a : Int[] = []
func test(inout b : Int[]) {
b += [1,2,3,4,5]
}
test(&a)
println(a)
???
func test(b: inout [Int])
... może to stara składnia; Swift dostałem dopiero w 2016 roku, a ta odpowiedź pochodzi z 2014 roku, więc może kiedyś było inaczej?
Inną opcją jest poproszenie konsumenta macierzy o to w razie potrzeby. Na przykład coś w rodzaju:
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
}
}
Następnie możesz dowolnie modyfikować tablicę w klasie Account. Zauważ, że to nie pomaga, jeśli chcesz również zmodyfikować tablicę z klasy kontrolera widoku.
Używanie inout
jest jednym z rozwiązań, ale nie wydaje mi się zbyt szybkie, ponieważ tablice są typami wartości. Stylistycznie osobiście wolę zwrócić zmutowaną kopię:
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]
inout
jest to uniwersalnie lepsze, ponieważ oszczędza baterię. Powiedziałbym, że czytelność, niezmienność i bezpieczeństwo wątków tego rozwiązania są ogólnie lepsze i że inout powinien być używany tylko jako optymalizacja w tych rzadkich przypadkach, gdy uzasadnia to przypadek użycia.
użyj a NSMutableArray
lub aNSArray
, które są klasami
w ten sposób nie musisz implementować żadnego opakowania i możesz użyć budowania w mostkowaniu
open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration
account
zmienną globalną i określaniuchats
właściwościChatsViewController
jak:var chats: [Chat] { return account.chats }
.