在 tableView Swift 中表示解析 JSON 的结果

Represent result of parsing JSON in tableView Swift

我从 Paul Hudson 的“Swift 的 100 天”开始学习 swift,我需要您的建议。 我正在尝试使用国家/地区的信息(首都、语言、货币等)制作应用程序,并坚持尝试在 tableView 中表示我的 JSON 解析结果。 这是我从 https://restcountries.com/v3.1/all

解析国家信息的结构
struct Country: Codable {
    let name: Name
    let cca2: String
    let capital: [String]?
    let population: Int
    let currencies: [String: Currency]?
}

struct Name: Codable {
    let common: String
    let official: String
}

struct Currency: Codable {
        let name: String?
        let symbol: String?
    }

我有货币方面的问题。我不明白如何在 tableView 中正确地表示它们。这是我的代码 ViewController:

import UIKit

class ViewController: UITableViewController {

    var countries = [Country] ()
    override func viewDidLoad() {
        super.viewDidLoad()
        let urlString = "https://restcountries.com/v3.1/all"
        if let url = URL(string: urlString) {
        if let data = try? Data(contentsOf: url) {
                parse(json: data)
                return
            }
           
        }
        
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        countries.count
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Country", for: indexPath)
        let country = countries[indexPath.row]
        cell.textLabel?.text = country.name.common
        cell.imageView?.image = UIImage(named: country.cca2.lowercased())

        
        return cell
    }
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if let vc = storyboard?.instantiateViewController(withIdentifier: "Detail") as? DetailViewController {
            vc.country = countries[indexPath.row]
            present(vc, animated: true)
        }
        
    }
    
    func parse(json: Data) {
       let decoder = JSONDecoder()
        do {
           let jsonCountries = try decoder.decode([Country].self, from: json)
            countries = jsonCountries
         }
        catch let error {
            print(error)
         }
    }
}

这是我的详情代码ViewController:

import UIKit

class DetailViewController: UITableViewController {
    var country: Country!
    let flag = "Flag"
    let general = "General"
    let currency = "Currency"
    var currencyName = ""
    var currencySymbol = ""
    lazy var sectionTitles = [flag, general, currency]
    lazy var currencies = country.currencies?.values
    
    override func viewDidLoad() {
        super.viewDidLoad()
        title = country.name.common
        getCurrencyName()
       
        }
       
    override func numberOfSections(in tableView: UITableView) -> Int {
        return sectionTitles.count
    }
    
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sectionTitles[section]
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch sectionTitles[section] {
        case flag:
            return 1
        case general:
            return 4
        case currency:
//            How make to return proper number's of rows??
            return 2
        default:
            return 0
        }
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch sectionTitles[indexPath.section] {
        case flag:
        let cell = tableView.dequeueReusableCell(withIdentifier: "Flag", for: indexPath)
            if let cell = cell as? FlagCell {
                cell.flagImageView.image = UIImage(named: country.cca2.lowercased())
            }
            return cell
            
        case general:
            let cell = tableView.dequeueReusableCell(withIdentifier: "Text", for: indexPath)
            cell.textLabel?.numberOfLines = 0
            switch indexPath.row {
            case 0:
                cell.textLabel?.text = "Common country name: \(country.name.common)"
            case 1:
                cell.textLabel?.text = "Official country name: \(country.name.official)"
            case 2:
                cell.textLabel?.text = "Capital: \(country.capital?[0] ?? "Unknown")"
            case 3:
                cell.textLabel?.text = "Population: \(country.population) people"
            default:
                return cell
            }
            return cell
            
            case currency:
            let cell = tableView.dequeueReusableCell(withIdentifier: "Text", for: indexPath)
            cell.textLabel?.numberOfLines = 0
            switch indexPath.row {
            case 0:
//          How to represent each currency of country?
                cell.textLabel?.text = "Currency name: \(currencyName)"
            case 1:
                cell.textLabel?.text = "Currency symbol: \(currencySymbol)"
           
            default:
                return cell
            }
            return cell
        default:
            break
        }
        return UITableViewCell ()
    }
    func getCurrencyName () {
        for currency in currencies! {
            currencyName = currency.name ?? ""
            currencySymbol = currency.symbol ?? ""
        }
       
    }
}

现在我了解如何表示每个国家/地区的一种货币,但是如何在不同的行中表示每个国家/地区的所有货币? 抱歉我的英语不是我的母语:)

您可以通过此访问每个国家/地区的货币数量,并在 numberOfRowsInSection 方法中使用它来 return 足够的货币行数:

country.currencies.count

剩下的就是使用 indexPath 的部分和行值填充 cellForRowAt 方法中的单元格。您应该遍历所选国家/地区的货币字典,并在一行中显示字典中的每个键和值对。

您可以像这样进行迭代:

for (key, value) in dict {
    // Use key and value here
}

我建议获取货币的排序列表。例如,对于给定的 Country:

let currencies = country.currencies?.sorted { [=10=].0 < .0 }

获取计数:

let count = currencies?.count ?? 0

要获取特定行的详细信息,应该是:

if let (code, currency) = currencies?[indexPath.row] {
    let currencyCode = code
    let currencyName = currency.name
    let currencySymbol = currency.symbol
}