在 table 视图中插入来自 REST API 的信息

Insert information from REST API in a table view

我今天问了另一个问题并修复了我的 Swift 4.2 代码后,我意识到由于某些配置文件我无法调试应用程序。

Errors shown when Testing application

该应用程序在启动时也会崩溃,所以我现在无能为力。我认为问题在于我如何从网络服务器(目前是我的电脑)获取信息。我对此很陌生,所以我的代码中可能有一些错误,所以请耐心等待。

import UIKit

class InfoTableViewController: UITableViewController {

    //MARK: Properties
    class Produs {
        var nume: String!
        var codBare: String!

        init(nume: String, codBare: String) {
            self.nume = nume
            self.codBare = codBare
        }
    }

    var produse = [Produs]()

    override func viewDidLoad() {
        super.viewDidLoad()

        //Load elements from server, theoretically
        loadProducts()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return produse.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // Table view cells are reused and should be dequeued using a cell identifier.
        let cellIdentifier = "InfoTableViewCell"

        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? InfoTableViewCell  else {
            fatalError("The dequeued cell is not an instance of InfoTableViewCell.")
        }

        // Fetches the appropriate meal for the data source layout.
        let produs = produse[indexPath.row]

        cell.nameMain.text = produs.nume
        cell.nameInfo.text = produs.codBare

        return cell
    }
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }

    //MARK: Private Methods
    private func loadProducts() { //This function retrieves information in a JSON format from the server
        var request = URLRequest(url: URL(string: "192.168.0.145")!)
        request.httpMethod = "GET"

        URLSession.shared.dataTask(with: request, completionHandler: { data, response, error -> Void in
            do {
                let decoder = JSONDecoder()
                let json = try decoder.decode([[String]].self, from: data!)
                print(json)
                for produs in json {
                    print(produs)
                    var nume_prod: String = produs[0] // Numele produsului
                    var cod_ext: String = produs[1]   // Codul de bare al produsului
                    var prod_obj = Produs(nume: nume_prod, codBare: cod_ext)
                    self.produse.append(prod_obj)
                }
            } catch {
                print("JSON Serialization error")
            }
        }).resume()
    }
}

我正在从服务器的 JSON 文件中获取信息,该文件是一个数组数组,如下所示:

[
  [
    "product1",
    "code1"
  ],
  [
    "product2",
    "code2"
  ],
  [
    "product3",
    "code3"
  ]
]

感谢您的帮助!

不要将 JSON 作为数组数组发送,而是将其作为字典数组发送。它大大简化了解码。

[
  {"name":"product1", "code":"code1"},
  {"name":"product2", "code":"code2"},
  {"name":"product3", "code":"code3"}
]

然后将模型声明为结构,从不将属性声明为使用非可选值初始化的隐式解包可选。如果您需要可选项,请将它们声明为常规可选 (?),否则为非可选

struct Produs {
    let name: String
    let code: String
}

loadProducts替换为

private func loadProducts() { //This function retrieves information in a JSON format from the server
    let url = URL(string: "192.168.0.145")!

    URLSession.shared.dataTask(with: url, completionHandler: {[unowned self] data, response, error in
        if let error = error { print(error); return }
        do {
            self.produse = try JSONDecoder().decode([Produs].self, from: data!)
            print(self.produse)
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        } catch {
            print(error)
        }
    }).resume()
}

并将cellForRowAt替换为

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

    // Fetches the appropriate meal for the data source layout.
    let produs = produse[indexPath.row]

    cell.nameMain.text = produs.name
    cell.nameInfo.text = produs.code

    return cell
}