URLSession.shared.dataTask(with: url, completionHandler: { })
Combine을 사용하지 않고 URLSession을 사용하는 경우 보통 위 코드와 같은 메소드를 사용하는데요. 이는 비동기적으로 Request를 하고 받은 Response를 completionHandler에 전달합니다.
Combine을 사용하면 URLSession으로 Publisher를 만들 수 있습니다. 이 Publisher는 비동기적으로 Request를 하고 받은 response를 발행합니다.
// AnyPublisher<Data, URLError>
URLSession.shared.dataTaskPublisher(for: url).eraseToAnyPublisher()
Combine에서는 네트워크 통신으로 받은 JSON을 struct로 디코딩 해주는 operator도 제공합니다. 이 경우 디코딩 에러가 발생할 수 있으므로 Publisher의 Error 타입을 정의할 때 URLError가 아니라 더 큰 타입인 Error를 정의해주어야 합니다.
struct SomeStruct: Codable {
let someProperty: String
}
// AnyPublisher<[Post], Error>
URLSession.shared.dataTaskPublisher(for: url)
.map { $0.data }
.decode(type: SomeStruct.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
URLSession의 CompletionHandler 안에서 UI를 업데이트 하는 코드를 사용할 때 Main Thread에서 실행해야 하듯이 dataTaskPublisher 역시도 백그라운드에서 실행하기 때문에 UI를 업데이트하기 전에는 .receive(on: RunLoop.main)를 통해서 메인 쓰레드에서 실행해야 한다고 명시해주어야 합니다. 이렇게 하면 .sink를 사용해서 UI를 업데이트할 때 메인 쓰레드에서 실행하게 됩니다.
URLSession.shared.dataTaskPublisher(for: url)
.map { $0.data }
.decode(type: SomeStruct.self, decoder: JSONDecoder())
.receive(on: RunLoop.main)
.eraseToAnyPublisher()