Home > Software design >  How do i fix mutating operator isn't mutable error?
How do i fix mutating operator isn't mutable error?

Time:08-24

I'm trying to modify a dictionary containing a string as the key and an integer as the value. However, when I try to add/minus 1 from the integer, it returns me that error. currCleanup is a Cleanup object, which are clean up sessions people can host. items_collected is a dictionary within a Cleanup object.


 @Published var firestore = Firestore.firestore()
    @Published var errorMessage: String = ""
    @Published private(set) var cleanups: [Cleanup] = []
    @Published var currCleanup: Cleanup
    
//the functions with the error
func addOneItem(itemName: String)
    {
        for (nam, num) in currCleanup.items_collected {
            if nam == itemName {
                num  = 1 //this is where the error occurs
            }
        }
        db.collection("Cleanups").document(currCleanup.username).updateData(["itemsCollected" : currCleanup.items_collected])
        
}
    
func delOneItem(itemName: String)
{
    for (nam, num) in currCleanup.items_collected 
    {
        if nam == itemName {
             num -= 1 //here too
        }
    }
        
    db.collection("Cleanups").document(currCleanup.username).updateData(["itemsCollected" : currCleanup.items_collected])
}

CodePudding user response:

When you iterate over value objects, you don't receive a reference to their values, but rather new variables, where the value is copied to.

In your code, num is not a reference to the dictionary value, but a totally new variable. Even if you add var before (nam, num), it won't work: You'll only change the value of the variable num, but not the stored-in-dictionary value. Consider this example:

var dict = ["One" : 1,
            "Two" : 2,
            "Three" : 3]

let keyToChange = "Two"
for var (key, value) in dict {
  if key == keyToChange {
    value = 4
  }
}

print(dict) // ["Two": 2, "Three": 3, "One": 1]

You need to access the dictionary value directly in order to change it:

var dict = ["One" : 1,
            "Two" : 2,
            "Three" : 3]

let keyToChange = "Two"
for (key, value) in dict {
  if key == keyToChange {
    dict[key] = 4
  }
}

print(dict) // ["Two": 4, "Three": 3, "One": 1]

On the other hand, there's no point in loop, you can just check whether the key exists and change its value directly:

var dict = ["One" : 1,
            "Two" : 2,
            "Three" : 3]

let keyToChange = "Two"
if dict[keyToChange] != nil {
  dict[keyToChange] = 4
}

print(dict) // ["Two": 4, "One": 1, "Three": 3]

In your code it could be this:

if let value = currCleanup.items_collected[itemName] {
  currCleanup.items_collected[itemName] = value   1
}

Instead of this:

for (nam, num) in currCleanup.items_collected {
  if nam == itemName {
    num  = 1 //this is where the error occurs
  }
}

CodePudding user response:

to increment your array of values at the given itemName, try this approach:

func addOneItem(itemName: String) {
    if currCleanup.items_collected[itemName] != nil {
        currCleanup.items_collected[itemName] = currCleanup.items_collected[itemName]!   1
        db.collection("Cleanups").document(currCleanup.username).updateData(["itemsCollected" : currCleanup.items_collected])
    }  
}

Similarly for delOneItem

  • Related