Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 4将数据从json保存到数组以在TableView中显示_Json_Swift_Uitableview_Tableview_Swift4 - Fatal编程技术网

Swift 4将数据从json保存到数组以在TableView中显示

Swift 4将数据从json保存到数组以在TableView中显示,json,swift,uitableview,tableview,swift4,Json,Swift,Uitableview,Tableview,Swift4,我试图将func getCoinData中的数据保存到数组sympolsCoin和数组sympolsCoin中,以便在我的TableView中使用它 我在同一个ViewController.swift文件中创建了此类: struct Coin: Decodable { let symbol : String let price_usd : String } 在我的视图控制器类中: var coins = [Coin]() var sympolsCoin = [String]() var

我试图将func getCoinData中的数据保存到数组sympolsCoin和数组sympolsCoin中,以便在我的TableView中使用它

我在同一个ViewController.swift文件中创建了此类:

struct Coin: Decodable {

let symbol : String
let price_usd : String } 
在我的视图控制器类中:

var coins = [Coin]()


var sympolsCoin = [String]()
var priceUSDcoin = [String]()



func getCoinData(completion: @escaping () -> ()) {
    let jsonURL = "https://api.coinmarketcap.com/v1/ticker/"
    let url = URL(string: jsonURL)

    URLSession.shared.dataTask(with: url!) { (data, response, error) in

        do {
            self.coins = try JSONDecoder().decode([Coin].self, from: data!)

            for info in self.coins {

                self.sympolsCoin.append(info.symbol)
                self.priceUSDcoin.append(info.price_usd)

                print("\(self.sympolsCoin) : \(self.priceUSDcoin)")

                completion()
            }

        }


        catch {
            print("Error is : \n\(error)")
        }
    }.resume()
}
当我在TableView中使用数组时,我得到了一个空表

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "BitcoinTableViewCell", for: indexPath) as! BitcoinTableViewCell

    cell.coinNameLable.text = sympolsCoin[indexPath.row]
    cell.priceLable.text = priceUSDcoin[indexPath.row]

    return cell

}

在ViewController类中创建tableView的出口,并将其命名为“tableView”,然后 试试这个代码:Swift 4

func getCoinData() {
    let jsonURL = "https://api.coinmarketcap.com/v1/ticker/"
    let url = URL(string: jsonURL)

    URLSession.shared.dataTask(with: url!) { (data, response, error) in

        do {
            self.coins = try JSONDecoder().decode([Coin].self, from: data!)

            for info in self.coins {

                self.sympolsCoin.append(info.symbol)
                self.priceUSDcoin.append(info.price_usd)

                print("\(self.sympolsCoin) : \(self.priceUSDcoin)")

                self.tableView.reloadData()
            }

        }

        catch {
            print("Error is : \n\(error)")
        }
  }.resume()
}
在ViewDidLoad中按如下方式调用此函数

 override func viewDidLoad() {
    super.viewDidLoad()
    getCoinData()
}

您需要从主线程更新tableView。这是一个很好的教训:始终从主线程更新UI。总是

do {
        self.coins = try JSONDecoder().decode([Coin].self, from: data!)

        for info in self.coins {

            self.sympolsCoin.append(info.symbol)
            self.priceUSDcoin.append(info.price_usd) 

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

            print("\(self.sympolsCoin) : \(self.priceUSDcoin)")

            completion()
        }

    }
然而,代码中还有另一个问题,即标签设置的方式无法工作。TableViewCells可以重复使用,所以我猜您在其他地方为它们提供了@IBOutlets。您应该在cellForRowAt中声明一个标签常量:

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

    let coinNameLabel = cell.viewWithTag(100) as! UILabel
    coinNameLabel.text = sympolsCoin[indexPath.row]
    let priceNameLabel = cell.viewWithTag(101) as! UILabel
    priceNameLabel.text = priceUSDcoin[indexPath.row]
}

上面的代码假设您在故事板中设置了两个标签,标签为100和101(假设您使用一个)

因为您使用的是
JSONDecoder
创建和填充
sympolsCoin
priceUSDcoin
的整个逻辑是无意义和冗余的

struct Coin: Decodable {
    private enum CodingKeys: String, CodingKey {
        case symbol, priceUSD = "price_usd"
    }
    let symbol : String
    let priceUSD : String 
} 

完成处理程序也是冗余的。接收数据后,只需在主线程上重新加载表视图:

func getCoinData() {
    let jsonURL = "https://api.coinmarketcap.com/v1/ticker/"
    let url = URL(string: jsonURL)

    URLSession.shared.dataTask(with: url!) { [unowned self] (data, response, error) in
        guard let data = data else { return }
        do {
            self.coins = try JSONDecoder().decode([Coin].self, from: data)
            DispatchQueue.main.async {
               self.tableView.reloadData()
            }

        } catch {
            print("Error is : \n\(error)")
        }
    }.resume()
}
viewDidLoad
中加载数据

override func viewDidLoad() {
    super.viewDidLoad()
    getCoinData()
}
cellForRow
中更新用户界面

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "BitcoinTableViewCell", for: indexPath) as! BitcoinTableViewCell

    let coin = coins[indexPath.row]
    cell.coinNameLable.text = coin.symbol
    cell.priceLable.text = coin.priceUSD

    return cell

}
**


**

我有一个小问题..当应用程序加载时,在我向下或向上滚动之前,不会在表视图中显示任何内容,然后显示数据!转到getCoinData(),将“self.tableView.reloadData()”替换为DispatchQueue.main.async{self.tableView.reloadData()}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "BitcoinTableViewCell", for: indexPath) as! BitcoinTableViewCell

    let coin = coins[indexPath.row]
    cell.coinNameLable.text = coin.symbol
    cell.priceLable.text = coin.priceUSD

    return cell

}
// First View Controller
//
//
//
import UIKit
struct Countory : Decodable {
    let name: String
    let capital: String
    let region: String
    let alpha2Code: String
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
  var listArr = [Countory]()
    @IBOutlet weak var tableView: UITableView! 
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self
        self.tableView.dataSource = self
        let url = "https://restcountries.eu/rest/v2/all"
        let urlObj = URL(string: url)!
        URLSession.shared.dataTask(with: urlObj) {(data, responds, Error) in
         do {
          self.listArr = try JSONDecoder().decode([Countory].self, from: data!)
             for country in self.listArr {

                    print("Country",country.name)
                    print("###################")
                    print("Capital",country.capital)
                 DispatchQueue.main.async {
                       self.tableView.reloadData()
                    }
                }
            } catch {
                print(" not ")
            }
        }.resume()
    }
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.listArr.count
    }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
        cell.label1.text = "Name: \(listArr[indexPath.row].name)"
        cell.lable2.text = listArr[indexPath.row].capital
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let homeView = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
          homeView.res = listArr[indexPath.row].region
          homeView.alpha = listArr[indexPath.row].alpha2Code
       self.navigationController?.pushViewController(homeView, animated: true)

    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }
}
// SecondViewController
class SecondViewController: UIViewController {
    @IBOutlet weak var label4: UILabel!
    @IBOutlet weak var label3: UILabel!

    var res = ""
    var alpha = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        self.label3.text = res
        self.label4.text = alpha

    }

}