How to Mutate Structs in Swift Using Map

How to mutate structs in Swift using map?

When using the brackets for arguments so that var works, you have to put the return type as well:

let inActionPersons = persons.map { (var p) -> Person in

p.active = false
return p
}

Swift - How to mutate a struct object when iterating over it

struct are value types, thus in the for loop you are dealing with a copy.

Just as a test you might try this:

Swift 3:

struct Options {
var backgroundColor = UIColor.black
}

var arrayOfMyStruct = [Options]()

for (index, _) in arrayOfMyStruct.enumerated() {
arrayOfMyStruct[index].backgroundColor = UIColor.red
}

Swift 2:

struct Options {
var backgroundColor = UIColor.blackColor()
}

var arrayOfMyStruct = [Options]()

for (index, _) in enumerate(arrayOfMyStruct) {
arrayOfMyStruct[index].backgroundColor = UIColor.redColor()
}

Here you just enumerate the index, and access directly the value stored in the array.

Hope this helps.

Use map to change struct property into new array

As per SE-0003, var function parameters have been removed from Swift 3 (also see this Q&A on the topic). The fact that the compiler crashes instead of generating an error message telling you this, is a bug – the compiler should never crash.

The solution is simply to simply create your own mutable copy of map(_:)'s function parameter.

let tuesdays = mondays.map { (d) -> Day in
var d = d // mutable copy of d that shadows the immutable function argument d
d.day = "Tuesday"
return d
}

Swift iOS -How come I can loop through an array of class objects and make property changes but not structs

The issue is caused by the fact that structs are value types, so mutating any properties of the struct mutates the struct instance itself as well and the closure input arguments in map are immutable. So when you try to mutate a property $0 in the closure of map, you are trying to mutate $0 itself in case map is called on a collection of value types.

On the other hand, classes are reference types, so mutating a property of a class instance doesn't mutate the instance itself.

A solution for your problem is to create a mutable copy of the struct instance in the map, mutate its name property and return that. There are two solutions, if you have a small number of properties on your type, calling its memberwise initialiser is easier, but if you have a lot of properties and only want to mutate a few, copying the struct and then modifying the necessary properties is the better choice.

let transformed = countryArr.map { Country(name: "Random", region: $0.region) }
let transformed2 = countryArr.map { country->Country in
var copy = country
copy.name = "Random"
return copy
}

Swift map doesn't work when changing array property

You are confusing reference and value types. While you working with Swift arrays of structs (struct is value-type), they creating a copy of anything you are putting in it. When you retrieving anything from the struct, it will make another copy of it. Basically map creation a new array of new structs taken from old array. You had to assign that array back:

private func select(partner: Partner){
parceiros = parceiros.map { (parceiro) -> Partner in
var _parceiro = parceiro
_parceiro.isSelected = parceiro.id == partner.id ? true : false
return _parceiro
}
}

Or you can use reference type: class. It means that instead of keeping copies of your structs, array will keep references to actual instance of the objects.

class Partner {
let id: Int
let nome: String
let icone: String
var isSelected : Bool
}

And the change a particular object inside it. You don't need to map then though. If you want to apply something for each member of array use forEach, if you want to apply something to part of array - use filter first:

private func select(partner: Partner){
parceiros.forEach { $0.isSelected = (parceiro.id == partner.id) }
}

How to change a value of struct that is in array?

With an array of struct Instrument, you can obtain the index for the Instrument with a particular identifier, and use that to access and modify a property of the Instrument.

struct Instrument {
let identifier: String
var value: Int
}

var instruments = [
Instrument(identifier: "alpha", value: 3),
Instrument(identifier: "beta", value: 9),
]

if let index = instruments.index(where: { $0.identifier == "alpha" }) {
instruments[index].value *= 2
}

print(instruments) // [Instrument(identifier: "alpha", value: 6), Instrument(identifier: "beta", value: 9)]

Why does this Swift struct require mutating?

Yes it is the default behaviour for a struct or enum that instance methods can not modify a property since they are value type. So you need to use mutating to override this behaviour.

The way you define your property, var or let, is still relevant for if you can change it from a mutable instance method or directly or not.

Since your property is not private you can still do

var g = Game(map: [[1]])
g.map.append([2])


Related Topics



Leave a reply



Submit