[英]Struct Gobal is being updated from another VC when it shouldn't be
We are creating a global struct where we store our products for a shopping cart. 我们正在创建一个全球结构,将我们的产品存储在购物车中。 Here is the code to create it 这是创建它的代码
class Cart : NSObject {
var allProductsInCart = [Product]()
class var sharedCart: Cart {
struct Static {
static let instance = Cart()
}
return Static.instance
}
}
In a separate view controller (called ProductVC), we are creating an instance of Product. 在一个单独的视图控制器(称为ProductVC)中,我们正在创建Product的实例。 We add that product to the array listed above, allProductsInCart like this and then change the value: 我们将产品添加到上面列出的数组中,将allProductsInCart这样,然后更改值:
let newProduct = Product()
newProduct.name = "Costco"
Cart.sharedCart.allProductsInCart.append(newProduct)
newProduct.name = "test2"
print ("value is: \(Cart.sharedCart.allProductsInCart[0].name)") //It prints "test2" not "Costco"
When the separate instance of product is modified in ProductVC, it is also changed in the struct. 在ProductVC中修改产品的单独实例时,其结构也会更改。 It is definitely a separate instance of product because it has a different variable name as seen above. 它绝对是产品的单独实例,因为它具有不同的变量名,如上所示。
It should print Costco still because the instance of Product within the ProductVC was modified after it was added to the struct and we want to print the instance in the struct. 它应该仍然打印Costco,因为ProductVC中的Product实例在添加到结构后已被修改,而我们想在结构中打印该实例。 Right? 对? Or do I have something wrong? 还是我有什么问题?
Is this normal behavior? 这是正常行为吗? Is there a reason this is happening? 是否有发生这种情况的原因? Is there a better way that a global variable is supposed to be created or a better way to create a sharedCart that we can access in any view controller? 是否应该有更好的方法来创建全局变量,还是有更好的方法来创建我们可以在任何视图控制器中访问的sharedCart?
This happens because newProduct
is a reference type (defined by a class) so when you change the name it just changes the name of the same reference. 发生这种情况是因为newProduct
是引用类型(由类定义),因此当您更改名称时,它只会更改同一引用的名称。 There is only one product in the cart at this point, not two. 此时,购物车中只有一种产品,而不是两种。 For reference, the easiest way to define a singleton in Swift would be 作为参考,在Swift中定义单例的最简单方法是
class Cart {
static let shared = Cart()
var products = [Product]()
}
So, just following your example: 因此,仅遵循您的示例:
let newProduct1 = Product()
newProduct1.name = "Costco"
Cart.sharedCart.products.append(newProduct1)
let newProduct2 = Product() // a new product
newProduct2.name = "test2"
// I assume you will want to add this product as well
Cart.shared.products.append(newProduct2)
//This will print "Costco"
print ("value is: \(Cart.sharedCart.products[0].name)")
The reason why allProductsInCart
is returning a different value is because of a concept known as Pass by Value
versus Pass by Reference
, it is nothing to do with the variable being static, or global. allProductsInCart
返回不同值的原因是由于一个称为“ Pass by Value
Pass by Reference
与“ Pass by Reference
Pass by Value
”的概念,这与静态或全局变量无关。
Product
is an object. Product
是一个对象。 All objects are known as Pass by Reference
. 所有对象都称为“ Pass by Reference
。 This means that the value of the object points to a location in memory, and whenever that value at that location in memory is changed, then, the value is changed everywhere else pointing to that location in memory. 这意味着对象的值指向内存中的某个位置,并且只要更改内存中该位置上的该值,该值就会在指向内存中该位置的其他所有位置处更改。
As allProductsInCart
stores an array of Product
, then it is storing an array of Objects
, which means, whenever you change the value of the object, you are changing the value of wherever it is stored in memory. 由于allProductsInCart
存储了一个Product
数组,因此它存储了一个Objects
数组,这意味着,无论何时更改对象的值,都将更改存储在内存中的值。
Edit: If you wanted it to be pass by value
, you would have to convert your array to a primitive data type. 编辑:如果希望pass by value
它,则必须将数组转换为原始数据类型。 For example: 例如:
var productName = [String]()
would prevent the value from being changed. var productName = [String]()
将防止更改值。
Your code would then look like: 您的代码将如下所示:
class Cart : NSObject {
var productName = [String]()
static let instance = Cart()
}
Then when you call 那你打电话的时候
let newProduct = Product()
newProduct.name = "Costco"
Cart.instance.productName.append(newProduct.name!)
newProduct.name = "test2"
print("Value is \(Cart.instance.productName[0])")
It will print Costco. 它将打印Costco。
Look at What's the difference between passing by reference vs. passing by value? 看一下按引用传递与按值传递有什么区别? For further information about pass by value
and pass by reference
有关pass by value
pass by reference
和pass by reference
pass by value
更多信息
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.