Selecting an array to add using the ternary "if" operator: "An immutable value ... only has mutating elements"

I have two arrays:

var addedToIgnoreList: [String] = []
var removedFromIgnoreList: [String] = []

      

I want to add a value to one of these arrays. If I do it like this:

(isUserIgnored ? removedFromIgnoreList : addedToIgnoreList).append("username")

      

I get Immutable value of type '[String]' only has mutating members named 'append'

It works if I use an intermediate variable:

var which = isUserIgnored ? removedFromIgnoreList : addedToIgnoreList
which.append("username")

      

Is using an additional variable the only way?


Update: The extra variable won't work, so the operator if

is the only option. See the accepted answer for an explanation.

+3


source to share


2 answers


This is all due to the fact that arrays are value types, not reference types. That is, variables do not point to arrays (unlike, say, NSArray

). They are arrays, and assigning an array to a new variable makes a new copy.

The reason you are getting this error is because:

(isUserIgnored ? removedFromIgnoreList : addedToIgnoreList).append(etc)

      

creates a temporary copy of one of the two arrays, and the call append

is made on that copy. And that copy will be immutable - that's a good thing, because if it wasn't, you might unintentionally mutate it (as you are trying here) only to find that no change has happened - your copy is made, mutated, and then discarded.

Keep in mind that these are:

var which = isUserIgnored ? removedFromIgnoreList : addedToIgnoreList
which.append("username")

      



also makes a copy. Therefore, the change which

will not change either the original array.

The easiest way to change the arrays themselves is to use the statement if

:

if isUserIgnored {
    removedFromIgnoreList.append("username")
}
else {
    addedToIgnoreList.append("username")
}

      

This will not make any copies and will change the arrays in place instead.

If, on the other hand, you want a fresh array with the value appended, perhaps the simplest way is to use the operator +

:

let newCopy =  (isUserIgnored ? removedFromIgnoreList : addedToIgnoreList) + ["username"]

      

+3


source


This way, by assigning the variable first which

, you won't mutate the original array.

What you need to do is add the element to the variable you want. I don't see any solution other than instructions if

.



if isUserIgnored {
    removedFromIgnoreList.append("username")
}
else {
    addedToIgnoreList.append("username")
}

      

+1


source







All Articles