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
}
}
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) }
}
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
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.