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
相关产品推荐
相关产品推荐

