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

SwiftUI登录应用:解析API错误响应并在Alert中显示

实现SwiftUI登录API自定义错误信息显示

1. 定义API错误响应模型

先根据API返回的JSON结构,创建匹配的Codable模型:

struct APIErrorResponse: Codable {
    let timestamp: String
    let status: Int
    let error: String
    let path: String
}

注意模型属性名要和JSON字段完全一致(包括大小写),如果字段名不匹配可以用CodingKeys映射,这里示例的字段名直接对应,无需额外处理。

2. 修改网络请求逻辑,提取自定义错误

在你的登录请求方法里,新增错误响应的解码逻辑,替代原本的固定错误提示:

func login(username: String, password: String) async throws -> LoginResponse { // LoginResponse为登录成功的响应模型
    guard let url = URL(string: "你的登录API地址") else {
        throw NetworkError.invalidURL
    }
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    // 设置请求头、序列化请求体(比如JSON格式的账号密码)...
    
    let (data, response) = try await URLSession.shared.data(for: request)
    
    guard let httpResponse = response as? HTTPURLResponse else {
        throw NetworkError.invalidResponse
    }
    
    // 区分成功/失败响应
    if (200...299).contains(httpResponse.statusCode) {
        return try JSONDecoder().decode(LoginResponse.self, from: data)
    } else {
        // 尝试解码API返回的错误信息
        do {
            let apiError = try JSONDecoder().decode(APIErrorResponse.self, from: data)
            throw NetworkError.apiError(apiError.error)
        } catch {
            // 解码失败时 fallback 到默认错误
            throw NetworkError.general("Something went wrong! Please try again")
        }
    }
}

// 自定义网络错误枚举,方便传递错误信息
enum NetworkError: Error, LocalizedError {
    case invalidURL
    case invalidResponse
    case apiError(String)
    case general(String)
    
    var errorDescription: String? {
        switch self {
        case .invalidURL:
            return "无效的请求地址"
        case .invalidResponse:
            return "服务器响应格式错误"
        case .apiError(let message):
            return message
        case .general(let message):
            return message
        }
    }
}

3. 在SwiftUI视图中绑定Alert显示错误

用@State变量管理错误状态和信息,触发Alert展示:

struct LoginView: View {
    @State private var username = ""
    @State private var password = ""
    @State private var showErrorAlert = false
    @State private var errorMessage = ""
    
    var body: some View {
        VStack(spacing: 16) {
            TextField("用户名", text: $username)
                .textFieldStyle(.roundedBorder)
            SecureField("密码", text: $password)
                .textFieldStyle(.roundedBorder)
            
            Button("登录") {
                Task {
                    do {
                        let response = try await login(username: username, password: password)
                        // 登录成功逻辑:跳转主页、保存用户信息等
                    } catch let error as NetworkError {
                        errorMessage = error.errorDescription ?? "Something went wrong! Please try again"
                        showErrorAlert = true
                    } catch {
                        errorMessage = "Something went wrong! Please try again"
                        showErrorAlert = true
                    }
                }
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
        .alert(isPresented: $showErrorAlert) {
            Alert(title: Text("登录失败"), message: Text(errorMessage), dismissButton: .default(Text("确定")))
        }
    }
}

解码失败的常见排查点

  • 打印实际响应数据:在解码前添加print(String(data: data, encoding: .utf8)),确认API返回的JSON格式是否和模型匹配
  • 检查请求头:确保请求的Accept和Content-Type设置为application/json,避免API返回非JSON格式的错误内容
  • 字段大小写:Swift属性名要和JSON字段完全一致,比如JSON里的error不能写成Swift里的Error

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:11:09