Collections immuables / mutables dans Swift

88

Je faisais référence au guide de programmation Swift d'Apple pour comprendre la création d'objets mutables / immuables (Array, Dictionary, Sets, Data) en langage Swift. Mais je ne pouvais pas comprendre comment créer des collections immuables dans Swift.

Je voudrais voir les équivalents dans Swift pour ce qui suit dans Objective-C

Réseau immuable

NSArray *imArray = [[NSArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];

Réseau mutable

NSMutableArray *mArray = [[NSMutableArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];
[mArray addObject:@"Fourth"];

Dictionnaire immuable

NSDictionary *imDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];

Dictionnaire mutable

NSMutableDictionary *mDictionary = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];
[mDictionary setObject:@"Value3" forKey:@"Key3"];
Pranav Jaiswal
la source

Réponses:

115

Tableaux

Créer un tableau immuable

Première manière:

let array = NSArray(array: ["First","Second","Third"])

Deuxième manière:

let array = ["First","Second","Third"]

Créer un tableau mutable

var array = ["First","Second","Third"]

Ajouter un objet au tableau

array.append("Forth")


Dictionnaires

Créer un dictionnaire immuable

let dictionary = ["Item 1": "description", "Item 2": "description"]

Créer un dictionnaire mutable

var dictionary = ["Item 1": "description", "Item 2": "description"]

Ajouter une nouvelle paire au dictionnaire

dictionary["Item 3"] = "description"

Plus d'informations sur Apple Developer

nicael
la source
12
Un tableau de «longueur fixe» serait plus précis. Ce n'est pas immuable.
Sulthan
1
immuable Dictionaryest vraiment immuable (opposé à Array)
Bryan Chen
@BryanChen Oh .. Merci!
nicael
@BryanChen Oui, j'ai oublié de supprimer var.
nicael
2
Ouaip. Plus d'informations sur l'immuabilité des tableaux dans cette question et ses réponses .
Matt Gibson
31

Swift n'a aucune baisse de remplacement pour NSArrayou les autres classes de collection en Objective-C.

Il existe des classes de tableaux et de dictionnaires, mais il convient de noter que ce sont des types «valeur», comparés à NSArray et NSDictionary qui sont des types «objet».

La différence est subtile mais peut être très importante pour éviter les bogues de cas de pointe.

Dans Swift, vous créez un tableau "immuable" avec:

let hello = ["a", "b", "c"]

Et un tableau "mutable" avec:

var hello = ["a", "b", "c"]

Les tableaux mutables peuvent être modifiés comme NSMutableArray:

var myArray = ["a", "b", "c"]

myArray.append("d") // ["a", "b", "c", "d"]

Cependant, vous ne pouvez pas passer un tableau mutable à une fonction:

var myArray = ["a", "b", "c"]

func addToArray(myArray: [String]) {
  myArray.append("d") // compile error
}

Mais le code ci-dessus fonctionne avec un NSMutableArray:

var myArray = ["a", "b", "c"] as NSMutableArray

func addToArray(myArray: NSMutableArray) {
  myArray.addObject("d")
}

addToArray(myArray)

myArray // ["a", "b", "c", "d"]

Vous pouvez obtenir NSMutableArrayle comportement de en utilisant un inoutparamètre de méthode:

var myArray = ["a", "b", "c"]

func addToArray(inout myArray: [String]) {
  myArray.append("d")
}

addToArray(&myArray)

myArray // ["a", "b", "c", "d"]

Réécrit cette réponse 2015-08-10 pour refléter le comportement actuel de Swift.

Abhi Beckert
la source
1
Cela a évidemment été changé maintenant. Un tableau constant est maintenant vraiment immuable, et un tableau variable est maintenant vraiment mutable. Ils sont passés en tant que valeurs , ils seront donc copiés lorsqu'ils sont affectés à une autre variable ou passés entre les fonctions. Ceci, cependant, n'a rien à voir avec la mutabilité ou l'immuabilité.
Balthazar
De plus, comme je l'ai mentionné dans ma réponse, être passé en tant que valeurs est pertinent pour la mutabilité / immuabilité puisque le seul moment où vous vous en souciez est lorsque vous passez un tableau à un autre code (ce qui peut le modifier).
Abhi Beckert
Mais si vous accédez au tableau en tant que propriété, vous pouvez toujours le modifier à partir d'un autre objet. L'un des avantages d'un tableau immuable est que vous pouvez le transmettre en toute sécurité à un autre objet, sans vous soucier de savoir si l'autre objet peut modifier l'original. Cette préoccupation n'existe plus lorsque les objets sont passés comme valeurs. Ainsi, des sémantiques différentes nécessitent des pratiques de codage différentes. EDIT: Je vois maintenant que vous avez reformulé le message, nous sommes donc d'accord. Je conviens que les différences sont importantes à prendre en compte. l'utilisation de collections mutables.
Balthazar
6

Il n'y a qu'un Arrayet un seul Dictionarytype dans Swift. La mutabilité dépend de la façon dont vous la construisez:

var mutableArray = [1,2,3]
let immutableArray = [1,2,3]

c'est-à-dire que si vous créez une assignation à une variable, elle est modifiable, alors que si vous créez une assignation à une constante, elle ne l'est pas.

AVERTISSEMENT: les baies immuables ne sont pas entièrement immuables! Vous pouvez toujours modifier leur contenu, mais pas leur longueur totale!

Coline
la source
1
Pour info: le comportement du tableau est en train de changer dans une prochaine beta; Je pense que tout le monde s'est entassé à ce sujet
russbishop
@xenadu Source? ETA sur cette version bêta?
Fichier analogique
Désolé, aucune source. Il est issu d'une discussion avec l'un des membres de l'équipe du compilateur. Il a également déclaré que la bêta 2 n'était en fait que quelques corrections de bogues déjà vérifiées et qu'elle n'avait rien de lié aux commentaires post-WWDC.
russbishop
5

Déclarez simplement votre (tout) objet ou variable avec

'let' key word -> for "constan/Immutable" array, dictionary, variable, object..etc.

et

'var' key word -> for "Mutable" array, dictionary, variable, object..etc. 

Pour plus d'informations

«Utilisez let pour créer une constante et var pour créer une variable. La valeur d'une constante n'a pas besoin d'être connue au moment de la compilation, mais vous devez lui attribuer une valeur exactement une fois. Cela signifie que vous pouvez utiliser des constantes pour nommer une valeur que vous déterminez une fois mais que vous utilisez à plusieurs endroits. "

var myVariable = 42
myVariable = 50
let myConstant = 42

Lisez «Le langage de programmation Swift».

iPatel
la source
Eh bien, dans le cas d'un tableau, cela ne fonctionne pas comme prévu. stackoverflow.com/a/24319712/623710
macshome
3

Si vous voulez travailler avec Array(Swift) comme avec NSArray, vous pouvez utiliser une simple fonction de pont. Exemple:

var arr1 : Array = []

arr1.bridgeToObjectiveC().count

Cela fonctionne de la même manière pour let.

Moti F.
la source
0

À partir de la documentation d'Apple:

Mutabilité des collections

Si vous créez un tableau, un ensemble ou un dictionnaire et que vous l'assignez à une variable, la collection créée sera modifiable. Cela signifie que vous pouvez modifier (ou muter) la collection après sa création en ajoutant, supprimant ou modifiant des éléments dans la collection. Inversement, si vous affectez un tableau, un ensemble ou un dictionnaire à une constante, cette collection est immuable et sa taille et son contenu ne peuvent pas être modifiés.

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID105

D'autres utilisations des collections immuables / mutables dépendent de la raison pour laquelle vous voulez qu'elles soient mutables / immuables. Les collections sont des types de valeur dans Swift, ce qui signifie que leur contenu est copié lorsqu'ils sont affectés à une autre valeur ou transmis à une autre fonction / méthode. Par conséquent, vous n'avez pas à vous soucier de savoir si une fonction de méthode de réception peut modifier le tableau d'origine. Par conséquent, vous n'avez pas besoin de vous assurer de renvoyer une collection immuable si votre classe contient une collection mutable, par exemple.

Balthazar
la source
0

[Non modifiable et immuable]

Le tableau de Swift peut être mis en sourdine

[let vs var, valeur vs type de référence]

Collection immuable [À propos] - est une structure de collection dont ne peut pas être modifiée. Cela signifie que vous ne pouvez pas ajouter, supprimer, modifier après la création

let + struct(comme Array, Set, Dictionary) est plus apte à être immuable

Il existe quelques classes (par exemple NSArray ) qui ne fournissent pas d'interface pour changer l'état interne

mais

class A {
    var value = "a"
}

func testMutability() {
    //given
    let a = A()
    
    let immutableArr1 = NSArray(array: [a])
    let immutableArr2 = [a]
    
    //when
    a.value = "aa"
    
    //then
    XCTAssertEqual("aa", (immutableArr1[0] as! A).value)
    XCTAssertEqual("aa", immutableArr2[0].value)
}   

Ce serait plutôt un unmodifiabletableau

yoAlex5
la source