Home > database >  How can i use this new get method for other models?
How can i use this new get method for other models?

Time:11-22

class Network {
    func getingData(completion : @escaping ([Model]) -> ()) async {
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            if let posts = try? JSONDecoder().decode([Model].self, from: data) {
                completion(posts)
            }
        }
        catch {
            print("error")
        }
    }
}

CodePudding user response:

You could try something like this approach, where getData works with Decodable, as was mentioned in the previous answer. In this particular example an array of Decodable.

struct Post: Decodable, Identifiable {
    let userId: Int
    let id: Int
    let title: String
    let body: String
    var comments: [Comment]?
}

struct Comment: Decodable, Identifiable {
    let postId: Int
    let id: Int
    let name: String
    let email: String
    let body: String
}

struct ContentView: View {
    let client = Network()
    @State var posts: [Post] = []  
    
    var body: some View {
        List {
            ForEach(posts, id: \.id) { post in
                Text(post.title)
            }
        }
        .task {
            posts = await client.getData(from: "https://jsonplaceholder.typicode.com/posts")
            // all comments from the first post
            let comments: [Comment] = await client.getData(from: "https://jsonplaceholder.typicode.com/posts/\(posts[0].id)/comments")
            print("\n---> comments: \(comments)")
        }
    }
}

class Network {

    func getData<T: Decodable>(from urlString: String) async -> [T] {
        guard let url = URL(string: urlString) else {
            print(URLError(.badURL))
            return [] // <-- todo, deal with errors
        }
        do {
            let (data, response) = try await URLSession.shared.data(for: URLRequest(url: url))
            guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
                print(URLError(.badServerResponse))
                return [] // <-- todo, deal with errors
            }
            let results = try JSONDecoder().decode([T].self, from: data)
            return results
        }
        catch {
            return [] // <-- todo, deal with errors
        }
    }
    
}

CodePudding user response:

Is it what you're looking for?

import Foundation

class Network {

  func getingData<Model: Decodable>(completion : @escaping ([Model]) -> ()) async {
    guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
      return
    }
    do {
      let (data, _) = try await URLSession.shared.data(from: url)
      if let posts = try? JSONDecoder().decode([Model].self, from: data) {
        completion(posts)
      }
    } catch {
      print("error")
    }
  }

}

If so, you only need to declare the Model type as generic. The only thing you need Model to conform is Decodable (the requirement of the JSONDecoder().decode([Model].self, from: data) call).

  • Related