Reputation: 964
The following code used to work until a few days ago. I have no idea what updated, maybe new 14.4? But it suddenly stopped working today with a nondescript error and i dont know what is wrong here.
FetchStockAPIApp.swift
import SwiftUI
@main
struct FetchStockAPIApp: App {
@StateObject public var stocks = TFViewModel()
var body: some Scene {
WindowGroup {
ContentView(stocks: stocks)
}
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@ObservedObject var stocks : TFViewModel
let isSSL = false
public var url : String = "http://10.0.0.41:8111/xyz123"
public var sslurl: String = "https://domain.name:8100/xyz123"
var body: some View {
ScrollView {
ForEach(stocks.tfstocks!, id: \.recid) { item in
Text("123")
}
}
.onAppear {stocks.fetchData(apiUrl: isSSL ? sslurl : url)}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(stocks: TFViewModel())
}
}
TFDataModel.swift
import SwiftUI
struct TFStock: Codable, Hashable {
var recid = UUID()
var symbol: String
var Close: Double
}
class TFViewModel: ObservableObject {
@Published var tfstocks: [TFStock]? = [TFStock]()
func fetchData(apiUrl: String) {
guard let url = URL(string: apiUrl) else {
print("URL is not valid")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data { // data is Optional, so
// you need to unwrap it
if let decodedResult = try?
JSONDecoder().decode(
[TFStock].self, from: data) {
// decoding is successful
DispatchQueue.main.async {
// assign the decoded articles to
// the state variable
self.tfstocks = decodedResult
}
//print(decodedResult)
return
}
}
print("Error: \(error?.localizedDescription ?? "Unknown error in API Fetch")")
}.resume()
}
}
remove the XXX from the SSL url to make that API call work in the code. I would be really grateful if someone could help me out here.
you need to turn isSSL = true to ON so that you use the domain name, since the other IP is just the same API on my local network.
Upvotes: 0
Views: 793
Reputation: 2882
I would suggest you to read more about Codable
protocol and what it’s used for. You can refer below link.
https://medium.com/@pleelaprasad/codable-protocols-in-swift-76f8b088c483.
The catch block prints below error for your code.
keyNotFound(CodingKeys(stringValue: "recid", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: "recid", intValue: nil) ("recid").", underlyingError: nil)) Error: Unknown error in API Fetch
I have verified the same using postman.
Below is the working solution.
import SwiftUI
struct ContentViewsss: View {
@ObservedObject var stocks : TFViewModel
let isSSL = true
public var url : String = "http://10.0.0.41:8111/xyz123"
public var sslurl: String = "https://domain.name/xyz123"
var body: some View {
ScrollView {
ForEach(stocks.tfstocks!, id: \.recid) { item in
Text(item.symbol)
}
}
.onAppear {stocks.fetchData(apiUrl: isSSL ? sslurl : url)}
}
}
struct TFStock: Codable, Hashable {
var recid = UUID()
var symbol: String
var Close: Double
private enum CodingKeys : String, CodingKey {
case symbol, Close
}
}
class TFViewModel: ObservableObject {
@Published var tfstocks: [TFStock]? = [TFStock]()
func fetchData(apiUrl: String) {
guard let url = URL(string: apiUrl) else {
print("URL is not valid")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data { // data is Optional, so
// you need to unwrap it
do{
let decodedResult = try
JSONDecoder().decode(
[TFStock].self, from: data)
// decoding is successful
DispatchQueue.main.async {
// assign the decoded articles to
// the state variable
self.tfstocks = decodedResult
}
//print(decodedResult)
return
}catch let error{
print(error)
}
}
print("Error: \(error?.localizedDescription ?? "Unknown error in API Fetch")")
}.resume()
}
}
Upvotes: 1