Modification de la valeur de struct dans un tableau

Je souhaite stocker des structures dans un tableau, accéder et modifier les valeurs de la structure dans une boucle for.

struct testing { var value:Int } var test1 = testing(value: 6 ) test1.value = 2 // this works with no issue var test2 = testing(value: 12 ) var testings = [ test1, test2 ] for test in testings{ test.value = 3 // here I get the error:"Can not assign to 'value' in 'test'" } 

Si je change la structure en classe, cela fonctionne. Quelqu’un peut-il me dire comment je peux changer la valeur de la structure.

Outre ce que dit @MikeS, rappelez-vous que les structures sont des types de valeur. Donc, dans la boucle for :

 for test in testings { 

une copie d’un élément de tableau est affectée à la variable de test . Toute modification que vous apportez est limitée à la variable de test , sans modifier les éléments du tableau. Cela fonctionne pour les classes car ce sont des types de référence, donc la référence et non la valeur est copiée dans la variable de test .

La manière appropriée de le faire est d’utiliser un for par index:

 for index in 0.. 

dans ce cas, vous accédez (et modifiez) à l'élément struct et non à une copie.

Eh bien, je vais mettre à jour ma réponse pour une compatibilité rapide.

Lorsque vous programmez beaucoup, vous devez modifier certaines valeurs des objects qui se trouvent dans une collection. Dans cet exemple, nous avons un tableau de structure et à condition de modifier la valeur d’un object spécifique. C’est une chose très courante dans n’importe quel jour de développement.

Au lieu d’utiliser un index pour déterminer quel object doit être modifié, je préfère utiliser une condition if, dont IMHO est plus commun.

 import Foundation struct MyStruct: CustomDebugSsortingngConvertible { var myValue:Int var debugDescription: Ssortingng { return "struct is \(myValue)" } } let struct1 = MyStruct(myValue: 1) let struct2 = MyStruct(myValue: 2) let structArray = [struct1, struct2] let newStructArray = structArray.map({ (myStruct) -> MyStruct in // You can check anything like: if myStruct.myValue == 1 { var modified = myStruct modified.myValue = 400 return modified } else { return myStruct } }) debugPrint(newStructArray) 

Remarquez tous les permet, ce mode de développement est plus sûr.

Les classes sont des types de référence, il n’est pas nécessaire de faire une copie pour changer une valeur, comme cela arrive avec les structures. En utilisant le même exemple avec des classes:

 class MyClass: CustomDebugSsortingngConvertible { var myValue:Int init(myValue: Int){ self.myValue = myValue } var debugDescription: Ssortingng { return "class is \(myValue)" } } let class1 = MyClass(myValue: 1) let class2 = MyClass(myValue: 2) let classArray = [class1, class2] let newClassArray = classArray.map({ (myClass) -> MyClass in // You can check anything like: if myClass.myValue == 1 { myClass.myValue = 400 } return myClass }) debugPrint(newClassArray) 

C’est une réponse très délicate. Je pense que tu ne devrais pas faire comme ça :

 struct testing { var value:Int } var test1 = testing(value: 6) var test2 = testing(value: 12) var ary = [UnsafeMutablePointer].convertFromArrayLiteral(&test1, &test2) for p in ary { p.memory.value = 3 } if test1.value == test2.value { println("value: \(test1.value)") } 

Pour Xcode 6.1, l’initialisation du tableau sera

 var ary = [UnsafeMutablePointer](arrayLiteral: &test1, &test2) 

Pour simplifier l’utilisation des types de valeur dans les tableaux, vous pouvez utiliser l’extension suivante (Swift 3):

 extension Array { mutating func modifyForEach(_ body: (_ index: Index, _ element: inout Element) -> ()) { for index in indices { modifyElement(atIndex: index) { body(index, &$0) } } } mutating func modifyElement(atIndex index: Index, _ modifyElement: (_ element: inout Element) -> ()) { var element = self[index] modifyElement(&element) self[index] = element } } 

Exemple d’utilisation:

 testings.modifyElement(atIndex: 0) { $0.value = 99 } testings.modifyForEach { $1.value *= 2 } testings.modifyForEach { $1.value = $0 } 

J’ai essayé la réponse d’Antonio qui semblait assez logique mais à ma grande surprise ça ne marche pas. En explorant ceci plus loin j’ai essayé ce qui suit:

 struct testing { var value:Int } var test1 = testing(value: 6 ) var test2 = testing(value: 12 ) var testings = [ test1, test2 ] var test1b = testings[0] test1b.value = 13 // I would assume this is same as test1, but it is not test1.value is still 6 // even trying testings[0].value = 23 // still the value of test1 did not change. // so I think the only way is to change the whole of test1 test1 = test1b 

J’ai fini par recréer un nouveau tableau de struct voir l’exemple ci-dessous.

 func updateDefaultCreditCard(token: Ssortingng) { var updatedArray: [CreditCard] = [] for aCard in self.creditcards { var card = aCard card.isDefault = aCard.token == token updatedArray.append(card) } self.creditcards = updatedArray } 

Vous avez assez de bonnes réponses. Je vais juste aborder la question sous un angle plus générique.

Autre exemple: mieux comprendre les types de valeur et leur signification:

 struct Item { var value:Int } var item1 = Item(value: 5) func testMutation ( item: Item){ item.value = 10 // cannot assign to property: 'item' is a 'let' constant } 

C’est parce que l’article est copié, quand il entre, il est immuable – par commodité.


 func anotherTest (item : Item){ print(item.value) } anotherTest(item: item1) // 5 

Aucune mutation ne se produit donc pas d’erreur


 var item2 = item1 // mutable copy created. item2.value = 10 print(item2.value) // 10 print(item1.value) // 5