I am trying to decode a JSON file from a URL; I am having issues initially. My product array is not receiving the JSON data; my code is below.
import SwiftUI
import SDWebImageSwiftUI
class DataManager: ObservableObject {
struct Returned: Decodable {
let product: [products]
}
@Published var productsArray: [products] = []
func fetchData(completion: @escaping () -> Void) {
guard let url = URL(string: "https://compassjobsapp.net/DummyJSONData.json") else {
print("Invalid URL")
completion()
return
}
URLSession.shared.dataTask(with: url) { data, _, error in
if let error = error {
print("Network error: (error)")
completion()
return
}
if let data = data {
print("Received Data: (String(data: data, encoding: .utf8) ?? "Unable to convert data to string")")
do {
let decodedData = try JSONDecoder().decode(Returned.self, from: data)
DispatchQueue.main.async {
self.productsArray = decodedData.product
print("Decoded Data: (decodedData)")
print("Products Array: (self.productsArray)")
}
print("Decoded Data: (decodedData)")
completion()
} catch {
print("Error decoding JSON: (error)")
completion()
}
}
}.resume()
}
}
struct ProductListView: View {
@ObservedObject private var dataManager = DataManager()
var body: some View {
NavigationView {
if dataManager.productsArray.isEmpty {
Text("No products available")
} else {
List(dataManager.productsArray) { products in
NavigationLink(destination: ProductDetailView(product: products)) {
VStack(alignment: .leading, spacing: 8) {
WebImage(url: URL(string: products.thumbnail))
.resizable()
.scaledToFit()
.frame(height: 150)
.cornerRadius(8)
Text(products.title)
.font(.headline)
.foregroundColor(.primary)
Text("Price: $(String(format: "%.2f", products.price))")
.font(.subheadline)
.foregroundColor(.secondary)
}
.padding(10)
}
}
.navigationTitle("Products")
.onAppear {
dataManager.fetchData {
print("Products Array: (dataManager.productsArray)")
// Print the products array to the console
print(dataManager.productsArray)
}
}
}
}
}
}
struct ProductDetailView: View {
let product: products
var body: some View {
Text("Product Detail View")
}
}
I have tried debugging the code with print statements at all places in the code and debugging with the console logs. No, one of the print statistics I created points to the Xcode counsel. My iOS simulator displays the tab titled "No products available."
Where am I getting wrong?
2
Answers
Change
To
Then move the
onAppear
You should see the
print
statements now.With your current setup the
else
never runs soonAppear
never runs.Try this approach, where you have the
.onAppear{...}
attached to theNavigationStack
(note NavigationView is deprecated). Also decode the json data using a valid
Returned
model andusing
@StateObject
for yourdataManager
.Works well for me, using MacOS 14.2, with Xcode 15.1, tested on real ios17 devices and MacCatalyst.
You will need to consult the docs of the API to determine if any of the properties
of
Returned
andProduct
are optional, and add?
to those.Full working code: