[iOS] KWDC에서 보고 울었던 에러 핸들링 하는법

유인호·2024년 10월 30일
1

iOS

목록 보기
72/73

0. 서론

KWDC에서 보다가 눈이 띠용하는 연사를 하나 찾아보았다. 핀테크 어쩌구저쩌구 친절한 에러 뭐시기 제목이였던거 같은데, 다른 연사 보고 아직 하고 계시길레 마지막에 한 1-2분 듣다가 우와 했었음. 자세한 내용을 못들어서 어케 구현했는지 알 수 없었으나, 마지막장의 구현한 모습을 어케 사용하는지만 사진을 찍어와서 내 나름대로 상상해서 재구성 해봄. 아래의 사진 말고는 아무런 정보가 없다.

아이디어는 다음과 같다.

  1. Combine이나 Rx같은거 보면 에러처리와 값처리를 한곳에 하게 되느데, 솔직히 에러처리 일일이 해주는거 귀찮으니까, 한번에 일괄적으로 에러 처리 한다.
  2. 근데 예외로 다른 작업을 추가적으로 해야한다면, Protocol을 받아서 처리해줄 수 있게 한다.

1. 환경

일단 나는 파이어베이스의 에러를 처리해야한다. 그리고 에러처리는 토스트 메시지로 할거임.

그럼 기본적인 에러 핸들링은 Toast를 띄우는걸로 한다.
거기에 Delegate를 어떻게 처리했는지 모르겠는데, 일단 대충 사진의 구현체 코드 보고 대충 이렇게 했겠거니 하고 만들어 보았다.

2. 코드

// Protocol
protocol ErrorHandlingDelegate {
    func present(for error: AppError)
}

// Convert Error
extension Error {
    func convertFirebaseError(isFireStoreError: Bool = true) -> AppError {
        let nsError = self as NSError
        // Authentication 에러 체크
        if isFireStoreError {
            // Firestore 에러 체크
            if let firestoreError = FirestoreErrorCode.Code(rawValue: nsError.code) {
                switch firestoreError {
                case .unavailable:
                    return .serverError
                case .unauthenticated:
                    return .sessionIsFired
                default:
                    return .undefinedError
                }
            }
        } else {
            if let authError = AuthErrorCode.Code(rawValue: nsError.code) {
                switch authError {
                case .networkError:
                    return .serverError
                case .userNotFound:
                    return .userNotFound
                case .wrongPassword:
                    return .wrongPassword
                case .emailAlreadyInUse:
                    return .duplicatedEmail
                case .sessionExpired:
                    return .sessionIsFired
                default:
                    return .undefinedError
                }
            }
        }
        
        return .undefinedError
    }
}

// handleError
extension Publisher where Failure == AppError {
    func handleError(_ delegate: ErrorHandlingDelegate? = nil) -> AnyPublisher<Output, Never> {
        self
            .catch { error in
                if let delegate {
                    delegate.present(for: error)
                    return Empty<Output, Never>().eraseToAnyPublisher()
                } else {
                    Utility.Toast.makeToast(message: error.toastMessage)
                    return Empty<Output, Never>().eraseToAnyPublisher()
                }
            }
            .eraseToAnyPublisher()
    }
}

// Example
extension ABCDViewModel: ErrorHandlingDelegate {
    func present(for error: AppError) {
        // 에러처리
    }
}

APIManager.fetchData()
	.handleError(self)
    .sink(with: self) { owner, value in
   		// 데이터 처리
    }

이렇게 에러핸들링을 처리해보았다. 실제로 연사에선 어떻게 구현했는진 아직 미궁속에 빠져있다. ㅋㅋㅋㅋ

profile
🍎Apple Developer Academy @ POSTECH 2nd, 🌱SeSAC iOS 4th
post-custom-banner

0개의 댓글