UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Day 60 Challenge

Forums > 100 Days of SwiftUI

I'm trying to start the day 60 challenge but I am stuck.

For now, I am just trying to keep it simple, to make sure that I am decoding the data from the URL successfully, but so far it isn't working.

It looks like the data is being downloaded just fine, but the problem is occurring when I try to decode the data into instances of the User struct that I have created.

The data being used in this project can be found at this link https://www.hackingwithswift.com/samples/friendface.json

I'm not sure if I have not set up the the types of my properties for the User or Friend structs correctly, or if the problem is coming from the Date not being formatted correctly, or if it is something else. If somebody could point me in the right direction, it would be much appreciated.

This is what I have so far, and it is printing "Unknown Error" as shown at the bottom of ContentView

import SwiftUI

struct ContentView: View {
    @State private var users = [User]()

    var body: some View {
        NavigationView {
            List(users) { user in
                Text("\(user.name)")
            }
            .onAppear(perform: loadUserData)
        }
    }

    func loadUserData() {
        guard let url = URL(string: "https://www.hackingwithswift.com/samples/friendface.json") else {
            print("Invalid URL")
            return
        }

        let request = URLRequest(url: url)

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let userData = data {
                let userDecoder = JSONDecoder()

                let registrationDateFormatter = DateFormatter()

                registrationDateFormatter.dateFormat = "y-MM-dd"

                userDecoder.dateDecodingStrategy = .formatted(registrationDateFormatter)

                if let decodedUsers = try? userDecoder.decode([User].self, from: userData) {
                    DispatchQueue.main.async {
                        users = decodedUsers
                    }

                    return
                }
            }

            print("Fetch Failed: \(error?.localizedDescription ?? "Unknown Error")")
        }.resume()
    }
}
import Foundation

struct User: Codable, Identifiable {
    var id: UUID
    let isActive: Bool
    let name: String
    let age: Int
    let company: String
    let email: String
    let address: String
    let about: String
    let registered: Date
    let tags: [String]
    let friends: [Friend]
}
import Foundation

struct Friend: Codable, Identifiable {
    var id: UUID
    let name: String
}

2      

A tip: Don't use try? when decoding JSON because, as you discovered, it swallows any errors that may occur by turning them into an Optional. You should only use the try? method when all you care about is the fact of failure but not the reason.

Instead, use a do {} catch {} block and check error (not localizedError) to see exactly what went wrong.

By using the do {} catch {} method instead of try?, you will see this error:

dataCorrupted(Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "registered", intValue: nil)], debugDescription: "Date string does not match format expected by formatter.", underlyingError: nil))

So in this case, it's that your dateDecodingStrategy doesn't match the date format used in the JSON. dateDecodingStrategy should indicate the date format that is used in the JSON, not the date format you want to get it in. The proper strategy for this particular JSON is .iso8601.

4      

Ok, I updated my code to look like this, and now it is working properly!

And, I was also able to see the detailed error information this way (before I switched to using the .iso8601 dateDecodingStrategy).

Thank you for the help!

import SwiftUI

struct ContentView: View {
    @State private var users = [User]()

    var body: some View {
        NavigationView {
            List(users) { user in
                Text("\(user.name)")
            }
            .onAppear(perform: loadUserData)
        }
    }

    func loadUserData() {
        guard let url = URL(string: "https://www.hackingwithswift.com/samples/friendface.json") else {
            print("Invalid URL")
            return
        }

        let request = URLRequest(url: url)

        URLSession.shared.dataTask(with: request) { data, response, error in
            guard let userData = data else {
                print("No data in response: \(error?.localizedDescription ?? "Unknown Error")")
                return
            }

            let userDecoder = JSONDecoder()

            userDecoder.dateDecodingStrategy = .iso8601

            do {
                users = try userDecoder.decode([User].self, from: userData)
                return
            } catch {
                print("Decoding Failed: \(error)")
            }

            print("Fetch Failed: \(error?.localizedDescription ?? "Unknown Error")")

        }.resume()
    }
}

3      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.