'Swift completion block with success and failure handler

I'm working on a Swift app's login process and I'd like to know if I should include both success and failure handlers to the function, which checks if the user has successfully logged in or not.

What I want to do here is trigger the successCompletion() block only when the user successfully logged in and otherwise display an Alert with a message. I feel the login function takes multiple arguments, and I think it is kind of hard to figure out it handles two completion handlers from LoginViewController. So, should I include both error and success handlers in the function or better to separate them somehow?

In my LoginViewController,

class LoginViewController: UIViewController {

    private let loginView = LoginView()

    @objc func loginButtonAction() {
        let idInputValue = loginView.loginIdTextField.text!
        let passInputValue = loginView.passwordTextField.text!
        
        LoginAPI().login(with: idInputValue, and: passInputValue, errorCompletion: show(message:)) { _ in
            let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as! SceneDelegate
            sceneDelegate.setRootVC(to: HomeViewController())
        }

    func showAlert(message: String) {
        let okAction = UIAlertAction(title: Alert.ButtonTitle.ok, style: .default, handler: nil)
        showAlert(title: Alert.Title.loginError, message: message, actions: [okAction], style: .alert)
    }

}

and my LoginAPI class,

import Alamofire
class LoginAPI {
    
    static var accountInfo: AccountInfo?
    private let loginEndpoint = "https://example.com"
    
    func login(with id: String, and password: String, errorCompletion: @escaping (_ m: String) -> Void?, successCompletion: @escaping () -> Void) {
        let parameter: [String: Any] = ["id": id, "password": password]
        
        AF.request(loginEndpoint, method: .post, parameters: parameter)
            .validate()
            .responseJSON { response in
                guard let data = response.data else {
                    errorCompletion(response.error)
                    return
                }
                
                let decoder: JSONDecoder = JSONDecoder()
                var accountInfo: AccountInfo?
                
                do {
                    accountInfo = try decoder.decode(AccountInfo.self, from: data)
                } catch {
                    errorCompletion(error)
                }
               
                LoginAPI.accountInfo = accountInfo
                
                DispatchQueue.main.async {
                    successCompletion()
                }
            }
    }
}

updated the function

func login(with id: String, and password: String, completed: @escaping (Result<AccountInfo, LoginError>) -> Void) {
    
    let parameter: [String: Any] = ["id": id, "password": password]
    AF.request(loginEndpoint, method: .post, parameters: parameter)
        .responseDecodable(of: AccountInfo.self) { response in

            switch(response.result) {
            case .success(let data):
                completed(.success(data))
            case .failure(let error):
                completed(.failure(.test))
            }
        }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source