SwiftUI中从其他View更新数据后HomeView员工列表不更新问题
问题解决:更新员工后列表不刷新的修复方案
核心问题原因
你的EmployeesViewModel中,updateEmployee方法在API更新成功的分支(.success)里没有更新@Published var employees: [User]数组,导致HomeView的List无法感知到数据变化,所以不会刷新UI。
修复步骤
1. 完善ViewModel的updateEmployee方法
在.success分支中,找到数组中对应ID的员工,替换为更新后的对象:
func updateEmployee(employee: User){ employeesRepository.updateEmployee(employee: employee) {[weak self] result in DispatchQueue.main.async { guard let self = self else { return } switch result { case .success(let success): // 找到对应ID的员工索引,替换为更新后的对象 if let index = self.employees.firstIndex(where: { $0.id == success.data.id }) { self.employees[index] = success.data } // 若想确保数据完全同步,也可以调用getEmployees()重新拉取全量数据 // self.getEmployees() case .failure(let error): print(String(describing: error)) switch error{ case .decodingError(_): self.messageError = "Error generando la decodificacion de la data \(error.localizedDescription)" case .encodingError: self.messageError = "Error generando la codificacion de la data \(error.localizedDescription)" case .noData: self.messageError = "Error con la data \(error.localizedDescription)" case .serverError(let statusCode): self.messageError = "Error del servidor \(statusCode), \(error.localizedDescription)" case .transportError(_): self.messageError = "Error del transporte de la peticion \(error.localizedDescription)" case .unknownedError(_): self.messageError = "Error desconocido \(error.localizedDescription)" case .urlError: self.messageError = "Error con la creación de la url \(error.localizedDescription)" } self.alertError = true } } } }
2. 修复Model层的编码解码错误
User结构体的枚举名是Codingkeys(小写k),不符合Swift命名规范且会导致编码失败,改为CodingKeys(大写K):
struct User: Decodable, Encodable{ let id: Int var name: String? var email: String? var sex: String? enum CodingKeys: String, CodingKey { case id case name case email case sex = "gender" } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.id = try container.decode(Int.self, forKey: .id) self.name = try container.decode(String.self, forKey: .name) self.email = try container.decode(String.self, forKey: .email) self.sex = try container.decode(String.self, forKey: .sex) } }
Employees结构体的属性名users与业务(员工)不符,改为employees提升可读性:
struct Employees: Decodable{ let employees: [User] enum CodingKeys: String, CodingKey { case data } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.employees = try container.decode([User].self, forKey: .data) } }
同时同步修改ViewModel中getEmployees方法的赋值逻辑:self.employees = result.employees。
3. 修复Repository层的数据源初始化问题
EmployeeRepository中缺少employeesDatasource的初始化,补充如下:
final class EmployeeRepository{ private let employeesDatasource = EmployeeDatasource() func updateEmployee(employee: User, completionBlock: @escaping (Result<Employee, NetworkError>) -> Void){ employeesDatasource.updateEmployee(employee: employee, completionBlock: completionBlock) } }
额外优化建议
- 使用EnvironmentObject传递ViewModel:在HomeView中通过
.environmentObject(employeesViewModel)传递ViewModel,子视图用@EnvironmentObject var employeesViewModel: EmployeesViewModel接收,避免手动传递,代码更简洁。 - 优化User结构体属性:给可选属性设置默认值(如
var name: String = ""),减少频繁处理??的冗余代码。 - 统一错误处理逻辑:把错误信息生成逻辑封装到
NetworkError的扩展中,减少ViewModel中的重复代码。 - 补充编码逻辑:给
User结构体添加encode(to:)方法,确保编码时字段名与API要求一致:
func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(name, forKey: .name) try container.encode(email, forKey: .email) try container.encode(sex, forKey: .sex) }
- 避免强制解包:用
guard let self = self else { return }提前解包,替换self!.alertError = true这类存在崩溃风险的代码。
内容的提问来源于stack exchange,提问作者Robinson Gonzalez
相关产品推荐
相关产品推荐

