2015-12-16 42 views
5

我創建了一個名爲ShoppingList的簡單結構。在Swift中更改For循環內的對象的屬性

struct ShoppingList { 

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

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

} 

接下來,我創建了一個ShoppingList陣列像這樣:

var shoppingLists = [ShoppingList]() 

之後,我取的購物清單等。現在,我通過shoppingLists迭代並更改標題,但它不斷更新的title屬性。

for var shoppingList in shoppingLists { 
    let items = getGroceryItemsByShoppingList(shoppingList) 
    shoppingList.groceryItems = getGroceryItemsByShoppingList(shoppingList) 
    shoppingList.title = "BLAH" // copied by value 
    print("ShoppingList \(shoppingList.title) has \(shoppingList.groceryItems.count) items") // THIS PRINT BLAH 
} 

print("shoppingLists[0].groceryItems.count \(shoppingLists[0].groceryItems.count)") // THIS PRINTS THE ORIGINAL CONTENT 

我相信,當我運行循環它是通過值複製,因此原始數組永遠不會改變。如何使用For循環更改原始數組?

+0

感謝您發佈一個清晰簡潔的問題,您已經重申了我對開發人員的信心。 – RyanR

回答

7

我會在這裏使用兩種方法。第一種方法是重新考慮ShoppingList是值類型還是引用類型。它有一個標識符的事實表明它確實是一個參考類型。如果兩個購物清單具有相同的內容,是否應該被視爲相同的清單?我懷疑不是。兩個具有相同標識符但內容不同的列表意味着什麼?如果這是非法的,那又往往指向它是一個參考類型,因爲它有一個身份。

如果它是一個引用類型,使之成爲final class

final class ShoppingList {} 

final類保護結構的簡單,因爲他們不吃虧繼承的問題。但是它們提供了引用語義。隨着這一變化,你的原始代碼將起作用。

解決這個問題的另一種方式是功能更強大,一切都是價值。在這種情況下,您可以通過映射你的購物清單的複印件實現這一目標:

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

這推動我們走向一個更實用的方法,但它使得標識符尷尬。所以如果你真的想這樣做,我想擺脫標識符,甚至可以使購物清單不變。在這種情況下,任何兩個相同的購物清單都是相同的清單,您可以使用更實用的風格。

但我懷疑製作ShoppingList引用類型是你更好的方法。

+0

我真的很喜歡你的論點值與參考類型。由於購物清單具有標識(shoppingListId),因此最好將其作爲參考類型..正如您所建議的那樣。 –

1

好的,我想通了。看來你現在這樣做的方式是通過在循環內部創建一個引用並改變其屬性(在結構的情況下不會改變原始實例)。你應該做的是直接打電話給他們:

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" 

這個作品,我查過了,不客氣!

+0

如果你省略「var」,那麼你正在處理的實例是「let」,這意味着常量,你不能改變常量。 –

+0

然而,你仍然可以改變它的屬性,男人 – EBDOKUM

+0

如果它是一個結構體,那就不行! –