我创建了一个名为ShoppingList的简单结构。
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]()
之后,我获取购物 list 等。现在,我遍历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循环更改原始数组?
最佳答案
我将在这里使用两种方法。第一种方法是重新考虑ShoppingList
是值类型还是引用类型。它具有标识符的事实向我表明,它实际上是引用类型。如果两个购物 list 的内容相同,是否应将其视为相同的 list ?我怀疑不是。具有相同标识符但内容不同的两个列表意味着什么?同样,如果那是非法的,则倾向于指出它是引用类型,因为它具有身份。
如果是引用类型,则将其设置为final class
:
final class ShoppingList {}
最终类保留了结构的简单性,因为它们没有继承问题。但是它们提供了引用语义。有了这一更改,您的原始代码就可以使用。
解决此问题的另一种方法是更实用,其中一切都是有值(value)的。在这种情况下,您可以通过映射购物 list 的副本来实现:
shoppingLists = shoppingLists.map { list in
var newList = list
newList.groceryItems = getGroceryItemsByShoppingList(list)
return newList
}
这将我们推向了一种更具功能性的方法,但是它使标识符变得笨拙。因此,如果您真的想这样做,我想摆脱标识符,甚至可以使购物 list 不可变。在这种情况下,任何两个相同的购物 list 都是相同的 list ,您可以使用更具功能性的样式进行编写。
但是我怀疑将
ShoppingList
用作引用类型是您更好的方法。