Je veux passer mon Swift Array
account.chats
à chatsViewController.chats
par référence (afin que, lorsque j'ajoute une discussion à account.chats
, chatsViewController.chats
pointe toujours sur account.chats
). C'est-à-dire que je ne veux pas que Swift sépare les deux tableaux lorsque la longueur de account.chats
change.
Les structures dans Swift sont passées par valeur, mais vous pouvez utiliser le modificateur inout
pour modifier votre tableau (voir les réponses ci-dessous). Les classes sont passées par référence. Array
et Dictionary
dans Swift sont implémentés en tant que structures.
Pour l'opérateur de paramètre de fonction, nous utilisons:
let (opérateur par défaut, nous pouvons donc omettre let) pour rendre un paramètre constant (cela signifie que nous ne pouvons pas modifier même la copie locale);
var pour le rendre variable (nous pouvons le modifier localement, mais cela n'affectera pas la variable externe qui a été transmise à la fonction); et
inout pour en faire un paramètre in-out. In-out signifie en fait passer variable par référence, pas par valeur. Et cela nécessite non seulement d’accepter valeur par référence, mais aussi de le transmettre par référence; transmettez-le donc avec & - foo(&myVar)
au lieu de simplement foo(myVar)
Alors faites-le comme ça:
var arr = [1, 2, 3]
func addItem(inout localArr: [Int]) {
localArr.append(4)
}
addItem(&arr)
println(arr) // it will print [1, 2, 3, 4]
Pour être exact, il ne s’agit pas simplement d’une référence, mais d’un véritable alias pour la variable externe. Vous pouvez donc réaliser cette astuce avec n’importe quel type de variable, par exemple un entier (vous pouvez lui affecter une nouvelle valeur), bien que ce ne soit pas nécessairement un type de variable. bonne pratique et il peut être déroutant de modifier les types de données primitifs comme celui-ci.
Définissez vous-même un BoxedArray<T>
qui implémente l'interface Array
mais délègue toutes les fonctions à une propriété stockée. En tant que tel
class BoxedArray<T> : MutableCollection, Reflectable, ... {
var array : Array<T>
// ...
subscript (index: Int) -> T {
get { return array[index] }
set(newValue) { array[index] = newValue }
}
}
Utilisez le BoxedArray
partout où vous utiliseriez un Array
. L'affectation d'une BoxedArray
se fera par référence. Il s'agit d'une classe. Les modifications apportées à la propriété stockée via l'interface Array
seront donc visibles pour toutes les références.
Pour Swift versions 3-4 (XCode 8-9), utilisez
var arr = [1, 2, 3]
func addItem(_ localArr: inout [Int]) {
localArr.append(4)
}
addItem(&arr)
print(arr)
Quelque chose comme
var a : Int[] = []
func test(inout b : Int[]) {
b += [1,2,3,4,5]
}
test(&a)
println(a)
???
Une autre option consiste à faire en sorte que le consommateur du tableau le demande au propriétaire. Par exemple, quelque chose comme:
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
}
}
Vous pouvez ensuite modifier le tableau autant que vous le souhaitez dans la classe Account. Notez que cela ne vous aide pas si vous souhaitez également modifier le tableau à partir de la classe du contrôleur de vue.
Utiliser inout
est une solution, mais cela ne me semble pas très rapide, car les tableaux sont des types valeur. Stylistiquement, je préfère personnellement renvoyer une copie mutée:
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]
utiliser un NSMutableArray
ou un NSArray
, qui sont des classes
de cette façon, vous n'avez pas besoin d'implémenter d'encapsuleur et pouvez utiliser la génération de pontage
open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration