이번에는 네트워크에 데이터 요청 시 Stutus Code 400, 500 에러가 발생한다면 유저에게 안내글을 보여줄 수 있도록 작업하였습니다.
실제로 종종 발생할 수 있는 429와 500 에러에 맞춰서 작업하였습니다.
안내글을 보여주는 방식은 알럿, 오버뷰, VStack 등 고민을 많이 해봤는데, 개인적으로 이번에는 VStack으로 코인 리스트 위에 나타나는 것이 좋을 듯해서 VStack을 활용하였습니다.
1. Status Code에 따라서 상태를 업데이트 해줄 수 있도록 작성합니다.
import Foundation
import Combine
class CoinDataService {
@Published var allCoins: [CoinModel] = []
@Published var status: StatusCode = .status200
var coinSubscription: AnyCancellable?
init() {
getCoin()
}
func getCoin() {
guard let url = URL(string: "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250&page=1&sparkline=false&price_change_percentage=24h") else { return }
coinSubscription = URLSession.shared.dataTaskPublisher(for: url)
.subscribe(on: DispatchQueue.global(qos: .default))
.tryMap { (output) -> Data in
guard let httpResponse = output.response as? HTTPURLResponse else {
throw URLError(.unknown)
}
switch httpResponse.statusCode {
case 200..<300:
DispatchQueue.main.async { [weak self] in
self?.status = .status200
}
return output.data
case 429:
DispatchQueue.main.async { [weak self] in
self?.status = .status429
}
throw NetworkingManager.NetworkingError.internalError429(url: url)
case 500..<599:
DispatchQueue.main.async { [weak self] in
self?.status = .status500
}
throw NetworkingManager.NetworkingError.serverError500(url: url, status: httpResponse.statusCode)
default:
DispatchQueue.main.async { [weak self] in
self?.status = .unknown
}
throw NetworkingManager.NetworkingError.badURLResponse(url: url, status: httpResponse.statusCode)
}
}
.receive(on: DispatchQueue.main)
.decode(type: [CoinModel].self, decoder: JSONDecoder())
.sink(receiveCompletion: NetWorkingManager.handleCompletion, receiveValue: { [weak self] (returnCoins) in
self?.allCoins = returnCoins
self?.coinSubscription?.cancel()
})
}
}
2. ViewModel에서 구독자를 생성해 업데이트해줍니다.
// Status Update
dataService.$status
.sink { [weak self] (statusCode) in
self?.status = statusCode
}
.store(in: &cancellables)
3. View에서 if 또는 case를 통해 예외처리를 해주면 완료입니다!
// 예시
// status429 혹은 status500이면 작성해둔 에러 문구를 띄웁니다.
VStack {
if viewModel.status == .status429 || viewModel.status == .status500 { StatusErrorView() }
생략..
}
이번 작업은 마땅히 좋은 자료를 찾을 수가 없어서 나름.. 고민하고 구글링 자료를 섞어가며(?) 작성하였습니다.
개발자만 볼 수 있게 오류메시지를 띄우는 자료는 많지만, 유저에게 알럿을 띄우거나 화면의 상태를 변화하는 자료는 생각보다 많이 안 보이더라고요.
어딘가 부족한 점이 분명 있을 것 같아요.
향후 이번에 작성한 코드를 조금더 보완해서 여러 프로젝트에서도 재활용할 수 있도록하면 좋겠습니다.
'Project > SwiftUI 블록와이드' 카테고리의 다른 글
[SwiftUI Project] 네트워크 모니터 추가하기 (유튜브 스타일) (2) | 2022.10.19 |
---|---|
[SwiftUI Project] 몇시간 전, 몇일 전 상대적 시간 구하기 RelativeDateTimeFormatter (0) | 2022.10.14 |
[SwiftUI Project] 예외처리: Json Data -> CoreData 백업하기 (0) | 2022.10.14 |
[SwiftUI Project] Skeleton Placeholder & Blink Animation 만들기 (0) | 2022.10.04 |
[SwiftUI Project] 당겨서 새로고침 Pull to Refresh (0) | 2022.10.03 |
댓글