如何从 API 调用中添加数据到 Swift 中的 tableviewcell
How to add data from API call to tableviewcell in Swift
我正在设置一个基本应用程序,它 returns 值来自对表视图中单元格的 API 调用。我在网上看到的各种示例将服务文件配置为直接从模型解码。但是,我正在尝试设置我的服务文件,以便它在可能的情况下从 ViewModel 解码。当我 运行 Xcode 中的应用程序时,我没有收到错误,但我也在我的表格视图中看到空白单元格。我对 Swift 中的 API 调用还很陌生。知道如何将其配置为 return API 在仍然使用 viewModel 的同时调用单元格的值吗?请参阅下面的代码:
在我的 WebService 文件中,我按如下方式设置我的 URLSession:
class WebService {
func getStocks(completion: @escaping (([SymbolViewModel]?) -> Void)) {
guard let url = URL(string: "https://island-bramble.glitch.me/stocks") else {
fatalError("URL is not correct")
}
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
completion(nil)
return
}
let symbols = try? JSONDecoder().decode([SymbolViewModel].self, from: data)
symbols == nil ? completion(nil) : completion(symbols)
}.resume()
}
}
ViewModel 的设置如下:
struct SymbolViewModel:Decodable {
let stockSymbol: Symbol
var symbol: String {
return self.stockSymbol.symbol.uppercased()
}
var price: String {
return String(format: "%.2f", self.stockSymbol.price)
}
}
模特:
struct Symbol: Decodable {
let symbol: String
let price: Double
}
具有 TableView 函数和 TableViewCell 的ViewController:
class ViewController: UIViewController {
let webService = WebService()
var symbols = [SymbolViewModel]()
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "TableViewCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "TableViewCell")
tableView.delegate = self
tableView.dataSource = self
webService.getStocks { symbols in
if let symbols = symbols {
DispatchQueue.main.async {
self.symbols = symbols
}
}
}
self.tableView.reloadData()
}
}
class TableViewCell: UITableViewCell {
@IBOutlet var mySymbol: UILabel!
@IBOutlet var myPrice: UILabel!
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
/// tableView functions
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return symbols.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TableViewCell.self), for: indexPath) as! TableViewCell
cell.mySymbol.text = symbols[indexPath.row].symbol
cell.myPrice.text = symbols[indexPath.row].price
return cell
}
}
错误信息:
keyNotFound(CodingKeys(stringValue: "stockSymbol", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"stockSymbol\", intValue: nil) (\"stockSymbol\").", underlyingError: nil))
0 elements
你的模型有误。
首先,如果您声明计算属性,则必须添加 CodingKeys
以防止计算属性被解码。这是错误的主要原因,但还有更多。
JSON是一个(一维)字典数组,对应的模型是
struct StockSymbol : Decodable {
let symbol : String
let price : Double
private enum CodingKeys : String, CodingKey { case symbol, price }
var priceAsString: String {
return String(format: "%.2f", price)
}
}
不需要另一个结构Symbol
。
解码
do {
let symbols = try? JSONDecoder().decode([StockSymbol].self, from: data)
completion(symbols)
} catch {
print(error)
completion(nil)
}
并且您必须在完成处理程序中重新加载 table 视图
webService.getStocks { symbols in
if let symbols = symbols {
DispatchQueue.main.async {
self.symbols = symbols
self.tableView.reloadData()
}
}
}
更复杂的方法是 Result
类型,它 returns 有效数据或错误
class WebService {
func getStocks(completion: @escaping (Result<[StockSymbol],Error>) -> Void) {
guard let url = URL(string: "https://island-bramble.glitch.me/stocks") else {
fatalError("URL is not correct")
}
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error { completion(.failure(error)); return }
completion( Result {try JSONDecoder().decode([StockSymbol].self, from: data!)})
}.resume()
}
}
并称之为
webService.getStocks { [weak self] result in
switch result {
case .success(let symbols):
DispatchQueue.main.async {
self?.symbols = symbols
self?.tableView.reloadData()
}
case .failure(let error): print(error) // or show the error to the user
}
}
我正在设置一个基本应用程序,它 returns 值来自对表视图中单元格的 API 调用。我在网上看到的各种示例将服务文件配置为直接从模型解码。但是,我正在尝试设置我的服务文件,以便它在可能的情况下从 ViewModel 解码。当我 运行 Xcode 中的应用程序时,我没有收到错误,但我也在我的表格视图中看到空白单元格。我对 Swift 中的 API 调用还很陌生。知道如何将其配置为 return API 在仍然使用 viewModel 的同时调用单元格的值吗?请参阅下面的代码:
在我的 WebService 文件中,我按如下方式设置我的 URLSession:
class WebService {
func getStocks(completion: @escaping (([SymbolViewModel]?) -> Void)) {
guard let url = URL(string: "https://island-bramble.glitch.me/stocks") else {
fatalError("URL is not correct")
}
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
completion(nil)
return
}
let symbols = try? JSONDecoder().decode([SymbolViewModel].self, from: data)
symbols == nil ? completion(nil) : completion(symbols)
}.resume()
}
}
ViewModel 的设置如下:
struct SymbolViewModel:Decodable {
let stockSymbol: Symbol
var symbol: String {
return self.stockSymbol.symbol.uppercased()
}
var price: String {
return String(format: "%.2f", self.stockSymbol.price)
}
}
模特:
struct Symbol: Decodable {
let symbol: String
let price: Double
}
具有 TableView 函数和 TableViewCell 的ViewController:
class ViewController: UIViewController {
let webService = WebService()
var symbols = [SymbolViewModel]()
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "TableViewCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "TableViewCell")
tableView.delegate = self
tableView.dataSource = self
webService.getStocks { symbols in
if let symbols = symbols {
DispatchQueue.main.async {
self.symbols = symbols
}
}
}
self.tableView.reloadData()
}
}
class TableViewCell: UITableViewCell {
@IBOutlet var mySymbol: UILabel!
@IBOutlet var myPrice: UILabel!
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
/// tableView functions
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return symbols.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TableViewCell.self), for: indexPath) as! TableViewCell
cell.mySymbol.text = symbols[indexPath.row].symbol
cell.myPrice.text = symbols[indexPath.row].price
return cell
}
}
错误信息:
keyNotFound(CodingKeys(stringValue: "stockSymbol", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"stockSymbol\", intValue: nil) (\"stockSymbol\").", underlyingError: nil))
0 elements
你的模型有误。
首先,如果您声明计算属性,则必须添加 CodingKeys
以防止计算属性被解码。这是错误的主要原因,但还有更多。
JSON是一个(一维)字典数组,对应的模型是
struct StockSymbol : Decodable {
let symbol : String
let price : Double
private enum CodingKeys : String, CodingKey { case symbol, price }
var priceAsString: String {
return String(format: "%.2f", price)
}
}
不需要另一个结构Symbol
。
解码
do {
let symbols = try? JSONDecoder().decode([StockSymbol].self, from: data)
completion(symbols)
} catch {
print(error)
completion(nil)
}
并且您必须在完成处理程序中重新加载 table 视图
webService.getStocks { symbols in
if let symbols = symbols {
DispatchQueue.main.async {
self.symbols = symbols
self.tableView.reloadData()
}
}
}
更复杂的方法是 Result
类型,它 returns 有效数据或错误
class WebService {
func getStocks(completion: @escaping (Result<[StockSymbol],Error>) -> Void) {
guard let url = URL(string: "https://island-bramble.glitch.me/stocks") else {
fatalError("URL is not correct")
}
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error { completion(.failure(error)); return }
completion( Result {try JSONDecoder().decode([StockSymbol].self, from: data!)})
}.resume()
}
}
并称之为
webService.getStocks { [weak self] result in
switch result {
case .success(let symbols):
DispatchQueue.main.async {
self?.symbols = symbols
self?.tableView.reloadData()
}
case .failure(let error): print(error) // or show the error to the user
}
}