4

I have the following struct, with some properties:

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

So I initialize a simple array and put some data in there:

var parceiros : [Partner] = [
    Partner(id: 1, nome: "Personal Profile", icone: "btPersonal",isSelected : true),
    Partner(id: 2, nome: "Professional Profile", icone: "btProfessional", isSelected: false)
]

But when I want to change the "isSelected" property with the high-order function Map, in the swift 4, the array don't update at all. Its weird because the var "_parceiro" have the right value in the return loop. But after the function the array returns to the original value.

private func select(partner: Partner){
    let _ = parceiros.map { (parceiro) -> Partner in
        var _parceiro = parceiro
        _parceiro.isSelected = parceiro.id == partner.id ? true : false
        return _parceiro
    }
}
2
  • Little hint: don't you have a warning on the line parceiros.map { (parceiro) -> Partner in telling on Result of call to 'map' is unused? Commented Oct 3, 2018 at 15:21
  • That wasn't a hint to silence it, it was because the response was in it. map() returns the transformed result, it doesn't modify the current object calling it, it's not a mutating method. Commented Oct 3, 2018 at 15:26

2 Answers 2

8

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) }
}
Sign up to request clarification or add additional context in comments.

Comments

3

map is not a mutating function. It can be used to iterate over a collection and apply the same transformation function to all elements of the collection, storing the transformed values in a new collection and returning that new collection.

You either need to use a simple loop and manually modify the selected value in the original array or simply use the return value of map.

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

parceiros = select(parceiros[0])

If you want to go for the map approach, you can also simplify the closure to a single line like below:

private func select(partner: Partner, from partners: [Partner]) -> [Partner] {
    return partners.map { return Partner(id: $0.id, nome: $0.nome, icone: $0.icone, isSelected: $0.id == partner.id)}
}

let selectedPartners = select(partner: parceiros[1], from: parceiros)

The approach using a regular loop:

private func select(partner: Partner){
    for i in parceiros.indices {
        parceiros[i].isSelected = parceiros[i].id == partner.id
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.