Iterating over and modifying a collection of structs in Swift -


suppose have structs like:

struct tattoo {     var imagetorso:uiimage?     var imagetorsourl:url?     var imagearms:uiimage?     var imagearmsurl:url? }  struct player {     var name:string = ""     var tattoos:[tattoo] = [] }  struct team {     var name:string = ""     var players:[player] = [] } 

now imagine have method passed in team value players. have iterate thru players , tattoos, download images , add them images variables on tattoos.

if use for in loop, won't work because each part of loop gets copy of members of array it's iterating over. i.e.:

for player in team.players {     tattoo in player.tattoos {         if let url = tattoo.imagetorsourl {             mynetframework.requestimage(from: url, completion: { image in                 tattoo.imagetorso = image             }         }     } } 

after doing iterations , completion blocks, still, original team variable identical prior doing of this. because each tattoo inner loop got copy of in player's tattoos array.

now know can use & pass structs reference in swift it's highly discouraged. know can use inout don't copied when come functions, discouraged.

i know these made classes avoid behavior.

but supposing don't have choice in matter -- structs -- seems way like:

for p in 0...team.players.count-1 {     t in 0...team.players[p].tattoos.count-1 {         if let url = team.players[p].tattoos[t].imagetorsourl {             mynetframework.requestimage(from: url, completion: { image in                 team.players[p].tattoos[t].imagetorso = image             }         }     } } 

this feels ugly , awkward, don't know how else around thing for in loops give copy of thing you're iterating through.

can enlighten me, or how is in swift?

i think got point: "when requirement modifying data, better use class instead." here question reference link you. why choose struct on class

struct fast , can use them prevent creating huge, messy class. struct provided immutable feature , make easier follow function programming

the significant benefit of immutable data free of race-condition , deadlocks. because read data , no worries problems caused changing data.

however, answer question, have few ways solve it.

1. renew whole data.

// first, need add constructors creating instances more easier. struct tattoo {     var imagetorso:uiimage?     var imagetorsourl:url?     var imagearms:uiimage?     var imagearmsurl:url?      init(imagetorso: uiimage? = nil, imagetorsourl: url? = nil, imagearms: uiimage? = nil, imagearmsurl: url? = nil) {         self.imagetorso = imagetorso         self.imagetorsourl = imagetorsourl         self.imagearms = imagearms         self.imagearmsurl = imagearmsurl     } }  struct player {     var name:string     var tattoos:[tattoo]      init() {         self.init(name: "", tattoos: [])     }      init(name: string, tattoos: [tattoo]) {         self.name = name         self.tattoos = tattoos     } }  struct team {     var name:string     var players:[player]      init() {         self.init(name: "", players: [])     }      init(name: string, players: [player]) {         self.name = name         self.players = players     } }  player in team.players {     tattoo in player.tattoos {         if let url = tattoo.imagetorsourl {              // catch old uiimage matching tattoo need updated.             ({ (needchangeimage: uiimage?) -> void in                 mynetframework.requestimage(from: url, completion: { image in                      // reconstruct whole team data structure.                     let newplayers = team.players.map { (player) -> player in                         let newtattos = player.tattoos.map { (tattoo) -> tattoo in                             if needchangeimage == tattoo.imagetorso {                                 return tattoo(imagetorso: image)                             } else {                                 return tattoo                             }                         }                         return player(name: player.name, tattoos: newtattos)                     }                     team = team(name: team.name, players: newplayers)                 })             })(tattoo.imagetorso)         }     } } 

these codes ugly, right? , there not awful performance issue caused going through whole data every network response; problem might causes retain cycle.

2. don't hold uiimage in data array.

redesign data structure, , use kingfisher download image synchronously.

kingfisher useful third party library. provides clean , simple methods use, , it's highly flexible.

let url = url(string: "url_of_your_image") imageview.kf.setimage(with: url) 

however, think best way if don't want use kingfisher change declaration struct class.


Comments

Popular posts from this blog

node.js - Node js - Trying to send POST request, but it is not loading javascript content -

javascript - Replicate keyboard event with html button -

javascript - Web audio api 5.1 surround example not working in firefox -