You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift do/try/catch处理API响应:如何在catch块获取LoginResponse的msg

如何在Swift登录API的Catch块中获取后端返回的错误提示msg

方案一:调整模型,在业务逻辑中直接判断(最简便)

如果后端无论登录成功还是失败,都返回LoginResponse结构(成功时token有值,失败时token为空或缺失),可以先修改模型让token变为可选类型,直接在成功回调里处理业务失败场景,不用走到catch块:

struct LoginResponse: Decodable {
    let token: String? // 改为可选,适配失败场景
    let msg: String
}

// 调用代码修改
Task {
    do {
        let request: Request<LoginResponse> = .postLogin(email: email, password: password)
        let response = try await URLSession.shared.decode(request)
        
        if let validToken = response.token {
            // 登录成功,存储token
            print("登录成功,token: \(validToken)")
        } else {
            // 登录失败,直接拿到后端提示
            print("登录失败:\(response.msg)")
        }
    } catch {
        // 处理网络中断、数据格式错误等系统级异常
        print("系统错误:\(error.localizedDescription)")
    }
}

这种方式把**业务失败(比如账号密码错误)和系统错误(网络、解码问题)**分开处理,逻辑更清晰,也不需要在catch块里额外解析错误信息。

方案二:自定义错误类型,在解码时捕获业务错误

如果后端在登录失败时返回非2xx的HTTP状态码,但响应体里依然包含msg错误提示,需要重构解码逻辑,把后端的错误信息包装成自定义错误抛出,这样就能在catch块中获取:

1. 定义自定义错误枚举

enum LoginServiceError: Error {
    case loginFailed(String) // 携带后端返回的msg
    case invalidResponse
    case networkFailure(Error)
    case decodingFailure(Error)
}

2. 重构URLSession的decode方法

加入HTTP状态码检查,失败时尝试解析LoginResponse获取错误信息:

extension URLSession {
    func decode<Value: Decodable>(
        _ request: Request<Value>,
        using decoder: JSONDecoder = .init()
    ) async throws -> Value {
        let (data, response) = try await data(for: request.urlRequest)
        
        // 校验HTTP响应合法性
        guard let httpResponse = response as? HTTPURLResponse else {
            throw LoginServiceError.invalidResponse
        }
        
        // 状态码非2xx时,尝试解码错误信息
        if !(200...299).contains(httpResponse.statusCode) {
            do {
                let errorResp = try decoder.decode(LoginResponse.self, from: data)
                throw LoginServiceError.loginFailed(errorResp.msg)
            } catch {
                throw LoginServiceError.decodingFailure(error)
            }
        }
        
        try Task.checkCancellation()
        // 正常解码成功响应
        do {
            return try decoder.decode(Value.self, from: data)
        } catch {
            throw LoginServiceError.decodingFailure(error)
        }
    }
}

3. 在调用处捕获自定义错误

Task {
    do {
        let request: Request<LoginResponse> = .postLogin(email: email, password: password)
        let response = try await URLSession.shared.decode(request)
        // 登录成功,存储token
        print("登录成功:\(response.token)")
    } catch let LoginServiceError.loginFailed(errorMsg) {
        // 直接拿到后端的错误提示
        print("登录失败:\(errorMsg)")
    } catch let LoginServiceError.networkFailure(error) {
        print("网络错误:\(error.localizedDescription)")
    } catch let LoginServiceError.decodingFailure(error) {
        print("数据解析错误:\(error.localizedDescription)")
    } catch {
        print("未知错误:\(error.localizedDescription)")
    }
}

补充说明

如果后端在失败时返回的是和LoginResponse不同的错误结构,需要单独定义对应的错误模型(比如LoginErrorResponse),在状态码异常时优先解码这个模型获取错误信息。

内容的提问来源于stack exchange,提问作者soleil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 11:50:01