Cannot Use Mutating Member ... Because Append

Cannot use mutating member ... because append?

Your problem can be reduced to the following:

let data = [1, 2, 3]
let data2 = [4, 5, 6]

let filteredData: [Int] = data
.map { $0 }
.append(contentsOf: data2.map { $0 })

The solution is to use concatenation instead of append:

let data = [1, 2, 3]
let data2 = [4, 5, 6]

let filteredData: [Int] = data
.map { $0 }
+ data2.map { $0 }

For an explanation, this is similar to:

let a: Int = 0
let b = a += 1 // this is append
let c = (a + 1) += 1 // this is append with a temporary expression

(you would be adding into something that is immediately discarded and the value would not be stored into c).

which obviously should be done as

let a: Int = 0
let b = a + 1

Note that even if you could append on temporary return value, append does not have a return value and your result assigned to filteredDataOpt would be Void.

The reason why temporary expression are constant (immutable) is to prevent you from doing similar errors.

Cannot modify my array - Cannot use mutating member on immutable value: function call returns immutable value

As the error tells you, your findPerson method is returning an immutable struct, so you can't edit it.

There are a few solutions to this -- two are included in the code sample below:

final class City {
var people = [Person]()

func addPetFor(id: UUID, newPets: [String]) {
guard let index = self.people.firstIndex(where: { $0.id == id }) else {
assertionFailure("Not found")
return
}
self.people[index].pets.append(contentsOf: newPets)
}

func addPetFor2(id: UUID, newPets: [String]) {
self.people = self.people.map {
if $0.id == id {
var personCopy = $0
personCopy.pets.append(contentsOf: newPets)
return personCopy
} else {
return $0
}
}
}
}

In both cases, the code has a reference to where the Person belongs in the people array, so it can modify it. Note that people also has to be var, not let, for the same reason -- it needs to be mutable.

Cannot use mutating member on immutable value error when appending to string in for loop

Since index is a let value inside the for loop , you can't use .append with it , instead you need

for (ind,value) in temples.enumerated()  {
temples[ind] = "\(value) triangles" // +=
}

SwiftUI: Cannot use mutating member on immutable value: 'shop' is a 'let' constant

The error tells the truth: Index variables in a loop are constants in Swift (since the initial release).

Due to value semantics you have to modify the Shop element in the shops array directly.

Add a function inside the view

func appendProduct(_ product: Product, to shop: Shop) {
guard let index = shops.firstIndex(where: {$0.id == shop.id}) else { return }
shops[index].container.append(product)
}

and call it

.navigationBarItems(trailing: Button {
appendProduct(Product(name: "Cheese"), to: shop)
} label: {
Text("add").bold()
})

Swift(UI) Error: Cannot use mutating member on immutable value: 'self' is immutable

Views are immutable in SwiftUI. You can only mutate their state, which is done by changing the properties that have a @State property wrapper:

@State var entries: [CEntries] = []

However, while you could do that, in your case CEntries is a class - i.e. a reference type - so while you could detect changes in the array of entries - additions and removals of elements, you won't be able to detect changes in the elements themselves, for example when .string1 property is updated.

And it doesn't help that it's an ObservableObject.

Instead, change CEntries to be a struct - a value type, so that if it changes, the value itself will change:

struct CEntries: Identifiable {
var id: UUID = .init()
var string1 = ""
var string2 = ""
}

struct AView: View {

@State var entries = [CEntries]()

var body: some View {
VStack() {
ForEach(entries) { entry in
VStack {
Text(entry.string1)
Text(entry.string2)
}
}
Button(action: {
self.entries.append(CEntries(string1: "he", string2: "lp"))
}) {
someButtonStyle()
}
}
}
}

Cannot use mutating member on immutable value: 'parent' is a 'let' constant?

As you are passing a struct (copies by value), you can't mutate function parameters without an inout.

Edit your code to this and try again:

static func createType(name: String, parent: inout FianceItem?) -> FianceItem {

You will also have to do this change if you want to pass nils:

var nilParent: FianceItem? = nil
var root = FianceItem.createType(name: "MyRoot", parent:&nilParent)

Mutating error when attempting to append an array of a struct

The issue is that a struct cannot change its own properties without the function that is changing those properties being marked mutating. You can’t mark body as mutating, but you can make children a @State var. @State variables are mutable, but only from within your view’s body property.

error: cannot use mutating member on immutable value: 'array' is a 'let' constant

The parameters to a function are effectively let constants. There are two ways you can resolve the problem which represent different programming paradigms. The first is to make the parameters inout and the second is to return the sorted array.

Using inout

func quicksort(array: inout [Int], lowIndex: Int, highIndex: Int)
{
// sort the array
}

Returning the sorted array

func quicksort(array: [Int]) -> [Int]
{
var sortingArray = array
// Do the pivot stuff

return quicksort(lower bit of sortingArray) + quicksort(upper bit of sortingArray)
}

You can do some jazzy stuff with generics and array slices in the latter case to make it look nice and eliminate the need to pass indexes.



Related Topics



Leave a reply



Submit