Odpowiedzi:
Struktury w Swift są przekazywane według wartości, ale możesz użyć inoutmodyfikatora, aby zmodyfikować swoją tablicę (patrz odpowiedzi poniżej). Klasy są przekazywane przez referencje. Arrayaw DictionarySwift są implementowane jako struktury.
NSArrayponieważ NSArraytablica Swift ma subtelne różnice semantyczne (takie jak typ referencyjny), co może prowadzić do większej liczby błędów.
inoutze 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.
inoutpozycja uległa zmianie, czylifunc addItem(localArr: inout [Int])
varnie jest już dostępny dla atrybutu parametru funkcji.
Zdefiniuj siebie a, BoxedArray<T>który implementuje Arrayinterfejs, 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 BoxedArraydowolnego miejsca, w którym chcesz użyć Array. Przypisanie BoxedArraywoli będzie przez odniesienie, jest to klasa, a tym samym zmiany w przechowywanej właściwości, poprzez Arrayinterfejs, będą widoczne dla wszystkich referencji.
Stringjest podtypem AnyALE, jeśli import Foundationnastępnie Stringstajesz 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 inoutjest 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]
inoutjest 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 NSMutableArraylub 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
accountzmienną globalną i określaniuchatswłaściwościChatsViewControllerjak:var chats: [Chat] { return account.chats }.