'Thread 4: Fatal error: 'try!' expression unexpectedly raised an error

I'm trying to learn to make an API call in swiftUI, I'm following the next tutorial https://www.youtube.com/watch?v=1en4JyW3XSI but the code is giving me an error that I can't find a solution for.

PostList.swift

import SwiftUI

struct PostList: View {
    
    @State var posts: [Post] = []
    
    var body: some View {
        List(posts) { post in
            Text(post.title)
                
        }
        .onAppear(){
            Api().getPosts { (posts) in
                self.posts = posts
            }
        }
    }
}

struct PostList_Previews: PreviewProvider {
    static var previews: some View {
        PostList()
    }
}

Data.swift

import SwiftUI

struct Post: Codable, Identifiable {
    var id = UUID()
    var title: String
    var body: String
}

class Api{

    func getPosts(completition: @escaping([Post]) -> ()){
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return }
        
        URLSession.shared.dataTask(with: url) { (data, _, _) in
            let posts = try! JSONDecoder().decode([Post].self, from: data!)
            
            DispatchQueue.main.async {
                completition(posts)
            }
           
        }
        .resume()
    }
}

The error that I'm getting is on here let posts = try! JSONDecoder().decode([Post].self, from: data!) and it's the next:

Thread 4: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "id", intValue: nil)], debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))

I have noticed that the guy in the tutorial uses let id = UUID() but that gives me a problem as well and I'm being asked to change it to var id = UUID().

I'm sorry if it's a very simple or stupid question, I just can't see to find a way around it.



Solution 1:[1]

You can see the exact problem by adding try - catch block for the exact error.

Like this

URLSession.shared.dataTask(with: url) { (data, _, _) in
    do {
        let posts = try JSONDecoder().decode([Post].self, from: data!)
        
        DispatchQueue.main.async {
            completition(posts)
        }
        
    } catch {
        print(error.localizedDescription)
    }
}

So now the error is printed:

The data couldn’t be read because it isn’t in the correct format.

It means you are decoding the wrong type.

The problem is here

struct Post: Codable, Identifiable {
    var id = UUID() //< Here

Here in json id have Int type and you are using UUID type.

So just change the data type UUID to Int. Like this

struct Post: Codable, Identifiable {
    var id : Int //< Here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 shim