TableViewCell with model from JSON Swift

swift
tableviewcell
ios

#1

Ошибка при заполнении таблицы ячейками:
Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Could not load NIB in bundle: ‘NSBundle </Users/irina/Library/Developer/CoreSimulator/Devices/F5DE087A-1131-48FD-AD2C-788E117A1AD9/data/Containers/Bundle/Application/D3AA195F-1D69-4551-B530-F32897B76355/FinalProjectExchangeRates.app> (loaded)’ with name ‘customCell’’

Мой джейсон:

{
"organizations": [
    {
      "title": "Universal Bank",
        "cityId": "7oiylpmiow8iy1smadi",
        "currencies": {
            "EUR": {
                "ask": "31.0500",
                "bid": "30.6500"
            },
            "USD": {
                "ask": "26.1300",
                "bid": "26.0000"
            }
        }
    },

Помогите, пожалуйста, правильно заполнить СегментедКонтрол во вьюконтроллере(мои кейсы это перечень банков и tableviewcell с данными валюта-курс покупки и продажи.
Это моя ТейблвьюСел:

class tableViewCell: UITableViewCell {
@IBOutlet weak var nameCurrency: UILabel!
@IBOutlet weak var exchangeRates: UILabel!
override func awakeFromNib() {
    super.awakeFromNib()
}
  func configure(exchangeRate: Bank, index: Int) {
self.nameCurrency.text = exchangeRate.rates[index].name
self.exchangeRates.text = " \(exchangeRate.rates[index].ask)  / \(exchangeRate.rates[index].bid)"
}
}

And ViewController with registered Cell:

class ExchangeViewController: UIViewController, UITableViewDelegate, UIScrollViewDelegate, UITableViewDataSource {
var zxc: Int!
private struct Constants {
    static let exchangeTableViewCellId = "customCell"
}
 var ratesSectionsArray = [Bank]()
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var segLabel: UISegmentedControl!
@IBAction func switchCustomBank(_ sender: UISegmentedControl) {
    switch segLabel.selectedSegmentIndex {
    case 0:
    case 1:
    case 2:
    case 3:
    default:
    }
override func viewDidLoad() {
    super.viewDidLoad()
    
    let nib = UINib(nibName: Constants.exchangeTableViewCellId, bundle: nil)
    tableView.register(nib, forCellReuseIdentifier: Constants.exchangeTableViewCellId)
    zxc = 0
   let baseUrlString = "http://resources.finance.ua/ru/public/currency-cash.json"
    guard let url = URL(string: baseUrlString) else { return }
    URLSession.shared.dataTask(with: url) {
        (data, response, error) in
        if let data = data {
            do{
                let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)
                guard let jsonDict = json as? [String: Any],
                    let organizationsArray = jsonDict["organizations"] as? [[String: Any]]
                else {return}
                for organization in organizationsArray{
                   guard let bank = Bank(json: organization)
                        else { continue }
                    self.ratesSectionsArray.append(bank)
                }
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            }
            catch{
                print("error")
            }
        }
    }.resume()
    }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return ratesSectionsArray.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: Constants.exchangeTableViewCellId, for: indexPath) as! tableViewCell
    let exchangesRates = ratesSectionsArray[indexPath.row]
    cell.configure(exchangeRate: exchangesRates, index: indexPath.row)
    return cell
}
}

#2

В тексте ошибки, если не читать лишнюю информацию, все написано.


Это значит что вот в этом месте
let nib = UINib(nibName: Constants.exchangeTableViewCellId, bundle: nil)
вы передаете строку Constants.exchangeTableViewCellId(в которой хранится переменная со значением customCell) , но xib с таким названием в проекте у вас нет. Полагаю, что вы ошиблись в названии.


#3

Можно попробовать так

Bank
class Bank: Codable {
let sourceID, date: String
let organizations: [Organization]
let orgTypes, currencies, regions, cities: [String: String]

enum CodingKeys: String, CodingKey {
    case sourceID = "sourceId"
    case date, organizations, orgTypes, currencies, regions, cities
}

init(sourceID: String, date: String, organizations: [Organization], orgTypes: [String: String], currencies: [String: String], regions: [String: String], cities: [String: String]) {
    self.sourceID = sourceID
    self.date = date
    self.organizations = organizations
    self.orgTypes = orgTypes
    self.currencies = currencies
    self.regions = regions
    self.cities = cities
}
}

class Organization: Codable {
let id: String
let oldID, orgType: Int
let branch: Bool
let title: String
let regionID: RegionID
let cityID: CityID
let phone, address, link: String
let currencies: [String: Currency]

enum CodingKeys: String, CodingKey {
    case id
    case oldID = "oldId"
    case orgType, branch, title
    case regionID = "regionId"
    case cityID = "cityId"
    case phone, address, link, currencies
}

init(id: String, oldID: Int, orgType: Int, branch: Bool, title: String, regionID: RegionID, cityID: CityID, phone: String, address: String, link: String, currencies: [String: Currency]) {
    self.id = id
    self.oldID = oldID
    self.orgType = orgType
    self.branch = branch
    self.title = title
    self.regionID = regionID
    self.cityID = cityID
    self.phone = phone
    self.address = address
    self.link = link
    self.currencies = currencies
}
}

enum CityID: String, Codable {
case the7Oiylpmiow8Iy1Smadi = "7oiylpmiow8iy1smadi"
case the7Oiylpmiow8Iy1Smadj = "7oiylpmiow8iy1smadj"
case the7Oiylpmiow8Iy1Smadk = "7oiylpmiow8iy1smadk"
case the7Oiylpmiow8Iy1Smadm = "7oiylpmiow8iy1smadm"
case the7Oiylpmiow8Iy1Smadn = "7oiylpmiow8iy1smadn"
case the7Oiylpmiow8Iy1Smadp = "7oiylpmiow8iy1smadp"
case the7Oiylpmiow8Iy1Smadr = "7oiylpmiow8iy1smadr"
case the7Oiylpmiow8Iy1Smadx = "7oiylpmiow8iy1smadx"
case the7Oiylpmiow8Iy1Smaec = "7oiylpmiow8iy1smaec"
}

class Currency: Codable {
let ask, bid: String

init(ask: String, bid: String) {
    self.ask = ask
    self.bid = bid
}
}

enum RegionID: String, Codable {
case ua07Oiylpmiow8Iy1Smadi = "ua,0,7oiylpmiow8iy1smadi"
case ua7Oiylpmiow8Iy1Smabz = "ua,7oiylpmiow8iy1smabz"
case ua7Oiylpmiow8Iy1Smac0 = "ua,7oiylpmiow8iy1smac0"
case ua7Oiylpmiow8Iy1Smaca = "ua,7oiylpmiow8iy1smaca"
case ua7Oiylpmiow8Iy1Smacc = "ua,7oiylpmiow8iy1smacc"
case ua7Oiylpmiow8Iy1Smacf = "ua,7oiylpmiow8iy1smacf"
case ua7Oiylpmiow8Iy1Smaci = "ua,7oiylpmiow8iy1smaci"
case ua7Oiylpmiow8Iy1Smacj = "ua,7oiylpmiow8iy1smacj"
case ua7Oiylpmiow8Iy1Smack = "ua,7oiylpmiow8iy1smack"
}
TableView
class TableViewController: UITableViewController {

var ratesSectionsArray: [Bank] = []


override func viewDidLoad() {
    super.viewDidLoad()

}



override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let baseUrlString = "http://resources.finance.ua/ru/public/currency-cash.json"
    guard let url = URL(string: baseUrlString) else { return }
    let session = URLSession.shared

    let task = session.dataTask(with: url) { (data, _, _) in
        guard let data = data else { return }
        do {
            let bankData = try! JSONDecoder().decode(Bank.self, from: data)

            self.ratesSectionsArray = [bankData]

            DispatchQueue.main.async {
                self.tableView.reloadData()

            }
        } catch {
        }
    }
    task.resume()
}


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if ratesSectionsArray.count >= 1 {
        return ratesSectionsArray[0].organizations.count
    } else {
        print(ratesSectionsArray)
        return 1
    }
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell

    if ratesSectionsArray.count >= 1 {
        cell.nameCurrency.text = ratesSectionsArray[0].organizations[indexPath.row].title

        let ask = ratesSectionsArray[0].organizations[indexPath.row].currencies["EUR"]?.ask as! String
        let bid = ratesSectionsArray[0].organizations[indexPath.row].currencies["EUR"]?.bid as! String

        cell.exchangeRates.text = " ask \(ask)    bid  \(bid))"
    } else {
    }

    return cell
}
}

Можно скачатьтут


#4

Спасибо огромное, особенно Psilc.
Это почти готовый код, даже с большей информацией чем я могла подумать!