Skip to content

Instantly share code, notes, and snippets.

@wata
Last active March 24, 2023 05:57
Show Gist options
  • Save wata/fbffc6ad5251e90d39cfba0483381971 to your computer and use it in GitHub Desktop.
Save wata/fbffc6ad5251e90d39cfba0483381971 to your computer and use it in GitHub Desktop.
A simple and convenience swift wrapper for firebase errors.
import Foundation
import FirebaseAuth
import FirebaseUI
import FirebaseFirestore
import FirebaseFunctions
import FirebaseStorage
struct FirebaseError: LocalizedError {
enum ErrorDomain {
case auth(code: AuthErrorCode, userInfo: [String: Any])
case fuiAuth(code: FUIAuthErrorCode, userInfo: [String: Any])
case firestore(code: FirestoreErrorCode, userInfo: [String: Any])
case functions(code: FunctionsErrorCode, details: Any?)
case storage(code: StorageErrorCode, userInfo: [String: Any])
case unknown(error: NSError)
}
let domain: ErrorDomain
let errorDescription: String?
var isCancelled: Bool {
switch domain {
case .auth(let code, _) where code == .webContextCancelled: return true
case .fuiAuth(let code, _) where code == .userCancelledSignIn: return true
case .firestore(let code, _) where code == .cancelled: return true
case .functions(let code, _) where code == .cancelled: return true
case .storage(let code, _) where code == .cancelled: return true
default: return false
}
}
init(_ error: Error) {
switch error {
case let error as NSError where error.domain == AuthErrorDomain:
domain = .auth(code: AuthErrorCode(rawValue: error.code)!, userInfo: error.userInfo)
case let error as NSError where error.domain == FUIAuthErrorDomain:
domain = .fuiAuth(code: FUIAuthErrorCode(rawValue: UInt(error.code))!, userInfo: error.userInfo)
case let error as NSError where error.domain == FirestoreErrorDomain:
domain = .firestore(code: FirestoreErrorCode(rawValue: error.code)!, userInfo: error.userInfo)
case let error as NSError where error.domain == FunctionsErrorDomain:
domain = .functions(code: FunctionsErrorCode(rawValue: error.code)!, details: error.userInfo[FunctionsErrorDetailsKey])
case let error as NSError where error.domain == StorageErrorDomain:
domain = .storage(code: StorageErrorCode(rawValue: error.code)!, userInfo: error.userInfo)
case let error as NSError:
domain = .unknown(error: error)
}
if case let error = error as NSError, let underlyingError = error.userInfo[NSUnderlyingErrorKey] as? NSError {
errorDescription = underlyingError.localizedDescription
} else {
errorDescription = error.localizedDescription
}
}
}
extension FirebaseError {
static let unknown = FirebaseError(NSError(domain: "", code: 0, userInfo: nil))
}
@wata
Copy link
Author

wata commented Apr 3, 2020

Usage

extension SignInViewController {
    func authUI(_ authUI: FUIAuth, didSignInWith authDataResult: AuthDataResult?, error: Error?) {
        guard let authUser = authDataResult?.user else {
            handleError(.init(error!)) // FUIAuth Error / Auth Error
            return
        }

        let userRef = Firestore.firestore().collection("users").document(authUser.uid)
        userRef.getDocument { (snapshot, error) in
            if let error = error {
                self.handleError(.init(error)) // Firestore Error
                return
            }
            if let snapshot = snapshot, snapshot.exists {
                print("Successfully signed in.")
                return
            }

            ...
        }
    }

    private func handleError(_ error: FirebaseError) {
        if case .fuiAuth(let code, _) = error.domain, case .userCancelledSignIn = code { return }

        print(error.localizedDescription)

        ...
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment