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).