본문 바로가기
Project/SwiftUI 블록와이드

[SwiftUI Project] 예외처리: StatusCode에 따라서 안내글 띄우기

by iOS_woo 2022. 10. 14.

서버 에러에 따른 안내글

이번에는 네트워크에 데이터 요청 시 Stutus Code 400, 500 에러가 발생한다면 유저에게 안내글을 보여줄 수 있도록 작업하였습니다.

코인게코의 StatusCode 설명 글

실제로 종종 발생할 수 있는 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() }
   생략..
}

 

이번 작업은 마땅히 좋은 자료를 찾을 수가 없어서 나름.. 고민하고 구글링 자료를 섞어가며(?) 작성하였습니다.

 

개발자만 볼 수 있게 오류메시지를 띄우는 자료는 많지만, 유저에게 알럿을 띄우거나 화면의 상태를 변화하는 자료는 생각보다 많이 안 보이더라고요.

 

어딘가 부족한 점이 분명 있을 것 같아요. 

향후 이번에 작성한 코드를 조금더 보완해서 여러 프로젝트에서도 재활용할 수 있도록하면 좋겠습니다.

 

 

 

댓글