2015-12-16 20 views
5

Ho creato una semplice struttura chiamata ShoppingList.Modifica delle proprietà dell'oggetto Inside For Loop in Swift

struct ShoppingList { 

    var shoppingListId :NSNumber 
    var title :String 
    var groceryItems :[GroceryItem] 

    init() { 
     self.title = "" 
     self.groceryItems = [GroceryItem]() 
     self.shoppingListId = NSNumber(integer: 0) 
    } 

} 

Poi ho creato una serie ShoppingList come questo:

var shoppingLists = [ShoppingList]() 

Dopo che prelevo le liste della spesa, ecc Ora, scorrere l'shoppingLists e cambiare il titolo, ma mai aggiorna la proprietà titolo .

Credo che quando eseguo il ciclo stia copiando in base al valore e quindi l'array originale non viene mai modificato. Come posso cambiare l'array originale usando il ciclo For?

+0

Grazie per aver postato una domanda chiara e concisa, hai rinnovato la mia fiducia negli sviluppatori. – RyanR

risposta

7

Ci sono due approcci che vorrei utilizzare qui. Il primo approccio consiste nel riconsiderare se ShoppingList è un tipo di valore o un tipo di riferimento. Il fatto che abbia un identificatore mi suggerisce che è davvero un tipo di riferimento. Se due liste della spesa hanno gli stessi contenuti, dovrebbe essere considerata la stessa lista? Sospetto di no. Cosa significherebbe avere due liste che hanno lo stesso identificatore, ma contenuti diversi? Se ciò è illegale, di nuovo, questo tende a indicare che è un tipo di riferimento perché ha un'identità.

Se si tratta di un tipo di riferimento, ne fanno un final class:

final class ShoppingList {} 

classi finali preservare la semplicità di struct perché non soffrono i problemi di eredità. Ma forniscono semantica di riferimento. Con quel cambiamento, il tuo codice originale funzionerebbe.

L'altro modo per avvicinarsi a questo è più funzionale, dove tutto è un valore. In tal caso, è possibile raggiungere questo mappando le copie dei vostri liste della spesa:

shoppingLists = shoppingLists.map { list in 
    var newList = list 
    newList.groceryItems = getGroceryItemsByShoppingList(list) 
    return newList 
} 

Questo ci spinge verso un approccio più funzionale, ma rende l'identificatore imbarazzante. Quindi, se davvero volessi andare in questo modo, mi piacerebbe sbarazzarmi degli identificatori e magari persino rendere immutabili le liste della spesa. In tal caso, due liste della spesa identiche sono la stessa lista e puoi scrivere in uno stile più funzionale.

Ma ho il sospetto che il fatto di rendere ShoppingList un tipo di riferimento sia l'approccio migliore.

+0

Mi piace molto il tuo argomento sui tipi di valore vs ref. Poiché la lista della spesa ha un identificativo (shoppingListId) è meglio averlo come ref type ... come suggerito. –

1

OK, l'ho capito. Sembra che il modo in cui lo fai ora sia creando un riferimento e cambiando le sue proprietà all'interno del ciclo (che non cambia un'istanza originale in caso di strutture). Quello che dovresti fare invece è chiamarli direttamente così:

for index in 0..<shoppingLists.count { 

//Stuff you do. Do the same way, just replace "shoppingList" to "shoppingLists[index]" 

shoppingLists[index].title = "BLAH" // copied by value 
    print("ShoppingList \(shoppingLists[index].title) has items") // THIS PRINT BLAH 

} 

print("shoppingLists[0].groceryItems.title: \(shoppingLists[0].title)") // Returns "shoppingLists[0].groceryItems.title: BLAH" 

Questo funziona, ho controllato, prego!

+0

Se si omette la "var", quindi si sta trattando l'istanza era "let" che significa costante e non è possibile modificare la costante. –

+0

Eppure è ancora possibile modificare le sue proprietà, man – EBDOKUM

+0

Non se è una struttura! –