API 호출의 값을 tableview의 셀로 반환하는 기본 앱을 설정하고 있습니다. 온라인에서 본 다양한 예제는 모델에서 직접 디코딩하도록 서비스 파일을 구성합니다. 그러나 가능한 경우 ViewModel에서 디코딩하도록 서비스 파일을 설정하려고합니다. Xcode에서 앱을 실행할 때 오류가 발생하지 않지만 테이블 뷰에 빈 셀이 표시됩니다. 나는 여전히 Swift의 API 호출에 상당히 익숙합니다. viewModel을 사용하는 동안 API 호출 값을 셀에 반환하도록 구성하는 방법은 무엇입니까? 아래 내 코드를 참조하십시오.
내 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은 (1 차원) 사전의 배열이며 해당 모델은 다음과 같습니다.
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)
}
완료 핸들러 내부에서 테이블 뷰를 다시로드해야합니다.
webService.getStocks { symbols in
if let symbols = symbols {
DispatchQueue.main.async {
self.symbols = symbols
self.tableView.reloadData()
}
}
}
더 정교한 방법은 Result
유형이며 유효한 데이터 또는 오류를 반환합니다.
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
}
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다