Download JSON from API in Swift w/ URLSession and escaping closures | Continued Learning #22
URLSession
을 통해 JSON
데이터를 받아온다.JSON
데이터를 해당 모델로 디코딩한다. private func downloadData(from url: URL, completionHandler: @escaping (_ data: Data?) -> ()) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil, let response = response as? HTTPURLResponse, response.statusCode >= 200 && response.statusCode < 300 else {
print("ERROR DOWNLOADING DATA")
completionHandler(nil)
return
}
completionHandler(data)
}.resume()
}
import SwiftUI
struct PostModel: Identifiable, Codable {
let userId: Int
let id: Int
let title: String
let body: String
}
class DownloadWithEscapingViewModel: ObservableObject {
@Published var posts: [PostModel] = []
init() {
getPosts()
}
func getPosts() {
guard let url = getUrl() else { return }
// BACKGROUND THREAD DOWNLOAD
downloadData(from: url) { data in
if let data = data {
guard let posts = try? JSONDecoder().decode([PostModel].self, from: data) else { return }
DispatchQueue.main.async { [weak self] in
self?.posts = posts
}
} else {
print("NO DATA RETURNED")
}
}
}
// GENERIC DATA DOWNLOAD HANDLER
private func downloadData(from url: URL, completionHandler: @escaping (_ data: Data?) -> ()) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil, let response = response as? HTTPURLResponse, response.statusCode >= 200 && response.statusCode < 300 else {
print("ERROR DOWNLOADING DATA")
completionHandler(nil)
return
}
completionHandler(data)
}.resume()
}
private func getUrl() -> URL? {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return nil }
return url
}
}
struct DownloadWithEscapingBootCamp: View {
@StateObject private var viewModel = DownloadWithEscapingViewModel()
var body: some View {
List {
ForEach(viewModel.posts) { post in
VStack(alignment: .leading) {
Text(post.title)
.font(.headline)
Text(post.body)
.foregroundColor(.gray)
.font(.body)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
}
downloadData
함수는 이스케이핑 클로저를 사용함으로써 비동기적으로 데이터를 받은 뒤 그 데이터를 처리할 수 있다. getPosts
함수에서 위 이스케이핑 클로저를 호출함으로써 데이터를 읽고 난 뒤에 데이터를 받았음이 보장된다. 데이터를 받았다면, 데이터를 디코딩한다.PostModel
구조체 데이터를 디코딩하는 과정은 Codable
프로토콜을 사용한 뒤 JSONDecoder
을 통해 불러오면 된다.