How do I create a custom struct to assign the contents of array into usable variables?

廉价感情. 提交于 2020-01-25 21:54:16

问题


I have a JSON function that previously mapped the contents of an array (countries, divisions, teams (not shown)) into seperate variables using this code:

let task = URLSession.shared.dataTask{ (response: URLResponse?, error: Error?) in

        DispatchQueue.main.async
            {

                if error != nil {
                    print("error=\(error)")
                    return
                }

                do{
                    let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
                        print (json)

                        if let arr = json?["countries"] as? [[String:String]] {
                            self.countryId = arr.flatMap { $0["id"]!}
                            self.countries = arr.flatMap { $0["name"]!}
                            self.teamsTableView.reloadData()
                            print ("Countries: ",self.countries)
                        }

                    if let arr = json?["divisions"] as? [[String:String?]] {

                        self.divisions = arr.flatMap { ($0["name"]! )}
                        self.divisionId = arr.flatMap { ($0["id"]! )}
                        self.teamsTableView.reloadData()
                        print ("Divisions: ",self.divisions)
                    }



                } catch{
                    print(error)
                }
        }
    }

However, I have since learned "that mapping multiple arrays as data source in conjunction with flatMap is pretty error-prone", and that I should use a custom struct instead.

How / Where do I begin to write a custom struct to assign the contents of this JSON array into seperate variables?

Thanks

UPDATE:

I have used the code as suggested below and I believe this is along the right lines. Below is the current output.

Countries: [KeepScore.SumbitScoreViewController.Country(name: Optional("Denmark"), countryId: Optional("1")), KeepScore.SumbitScoreViewController.Country(name: Optional("Belgium"), countryId: Optional("2")), KeepScore.SumbitScoreViewController.Country(name: Optional("Brasil"), countryId: Optional("3")),

However by the looks of it, it is also putting the countryId into the variable and I'd like just the name so I could call it in a UITable...What are the next steps in doing this?


回答1:


Same idea as you were doing, except instead of mapping each individual property you map the whole country.

//define a struct
struct Country {
    var name: String?
    var countryId: String?

    init(_ dictionary: [String : String]) {
        self.name = dictionary["name"]
        self.countryId = dictionary["id"]
    }
}

//defined in your class
var countries = [Country]()

//when parsing your JSON
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print (json)

if let arr = json?["countries"] as? [[String : String]] {
    self.countries = arr.flatMap { Country($0) }
    print ("Countries: ",self.countries)
}

Apply the same idea to divisions.

Edit:

In the code you've posted, you extract both the name and the id, that's why I included both in the struct. So you can remove the id from the struct if you wish, or add other variables in the future. Then when you want to extract them and use them in your table view you just do:

let country = countries[indexPath.row]
cell.textLabel.text = country.name


来源:https://stackoverflow.com/questions/40343981/how-do-i-create-a-custom-struct-to-assign-the-contents-of-array-into-usable-vari

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!