简体   繁体   English

不应该从另一个VC更新Struct Gobal

[英]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 referencepass by reference pass by value更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 枚举不应该初始化 - Enum being initialised when it shouldn't be iOS-不应该调整UITableViews的大小 - iOS - UITableViews are being resized when they shouldn't be 从另一个VC在第二个VC上加载UIWebView - loading a UIWebView on second VC from another VC 映像不是从一个VC到另一个VC - The image is not from one VC to another VC 从另一个VC返回VC时,如何清除UITableVIew中的所有检查? - How do I clear all checks in UITableVIew when VC is returned to from another VC? 从一个VC切换到另一个VC时,将数据保留在视图控制器中 - Retaining Data in a View Controller When Switching from One VC to Another 模态呈现另一个VC时,如何从当前VC中隐藏ios中的状态栏? - how to hide status bar in ios from a current VC when presenting another VC modally? 当使用ShowNav而不是UINavigationController弃用的Show而不是Push时,显示的VC没有navigationItem - When using Show instead of Push, which is deprecated, with UINavigationController, the VC being shown doesn't have navigationItem 在下一个VC中将文本从单元格传输到label时,第一次打开VC时不会出现 - When transferring text from a cell to a label in the next VC, it doesn't appear the first time the VC is opened ViewController将Swift从一个VC推送到另一个VC并返回 - ViewController Pushing Swift From One VC to Another VC And Returning back
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM