如何仅将编辑过的非空参数传入服务调用?
如何仅将编辑过的非空参数传入服务调用?
看起来你现在的问题是接口请求时会把所有可选字段(比如fName、mName)都塞进参数里,哪怕是空字符串或者没修改过的,你只想传修改过的非空参数,同时保留那些必填的ID参数对吧?我给你两种适配思路,你可以根据需求选:
方案1:只传「修改过的非空字段」(精准匹配你的需求)
这个方案会跟踪你实际修改过的字段,只把这些字段里有值的部分传到接口,完全符合你“改了哪个传哪个”的要求。
步骤1:在ViewModel里加个“修改跟踪器”
先在你的ViewModel里加一个集合,专门记录哪些profile字段被修改过:
class YourViewModel: ObservableObject { @Published var profile: ProfileData? = nil // 新增:记录修改过的字段名 @Published var modifiedProfileFields = Set<String>() // ... 其他现有代码 }
步骤2:修改TextField的Binding,标记修改的字段
把每个TextField的set闭包改一下,当字段值真的变化时,把对应的字段名加入跟踪集合:
labeledTextField( title: "staffProfile_firstName".localized(), placeholder: "staffProfile_firstName".localized(), text: Binding( get: { viewModel.profile?.fName ?? "" }, set: { // 先处理空值转nil的逻辑,和你原来的逻辑一致 let newValue = $0.isEmpty ? nil : $0 // 只有当值真的变化时,才更新并标记修改 if viewModel.profile?.fName != newValue { viewModel.profile?.fName = newValue viewModel.modifiedProfileFields.insert("fName") } } ), disabled: false ) // 同理修改mName、lName等其他TextField的set闭包,对应插入"mName"、"lName"等字段名
步骤3:重构接口参数构建逻辑
在staffUpdateProfile方法里,先放必填的ID参数,再只把跟踪到的、有非空值的字段加进去:
func staffUpdateProfile(titleID: Int, maritialStatusID: Int, relationshipWithMemberId: Int, bloodGroupID: Int, relegionID: Int, nationalityID: Int) async { guard APIManager.shared.isConnectedToInternet else { showInfoToast(message: "No internet connection.") return } let url = APIEndPoint.userSendStaffProfileRequest // 1. 先初始化必填的ID参数,这些是必须传的 var params: [String: Any] = [ "titleID": titleID, "maritialStatusID": maritialStatusID, "relationshipWithMemberId": relationshipWithMemberId, "bloodGroupID": bloodGroupID, "relegionID": relegionID, "nationalityID": nationalityID ] // 2. 把所有可选字段的键和对应值存成数组,方便遍历 let optionalFields: [(key: String, value: Any?)] = [ ("fName", profile?.fName), ("mName", profile?.mName), ("lName", profile?.lName), ("mobile", profile?.mobile), ("alternateMobile", profile?.alternateMobile) ] // 3. 只把「修改过的」且「非空」的字段加入参数 for field in optionalFields { if modifiedProfileFields.contains(field.key), let fieldValue = field.value { params[field.key] = fieldValue } } // ... 后面的接口请求逻辑不变,记得更新成功后清空跟踪集合 do { let model: CommonModel = try await APIManager.shared.asyncCallDecodableApiRequest( with: url, method: .post, params: params, showHud: true ) if model.status == "ok" { showSuccessToast(message: model.message ?? "Profile updated successfully.") self.isProfileDataEdited = false // 重置跟踪集合,下次修改重新记录 self.modifiedProfileFields.removeAll() } else { showErrorToast(message: model.message ?? "Update failed.") } } catch { await showInfoToastOnMainAction(message: error.localizedDescription) } }
方案2:传「所有非空字段」(更简单,适合不需要精准跟踪修改的场景)
如果你其实不在乎是否修改过,只是不想传空字符串或者nil的参数,那这个方案更简单:直接遍历所有可选字段,只把有值的加进参数里就行,不用跟踪修改记录。
修改staffUpdateProfile里的参数构建部分:
func staffUpdateProfile(titleID: Int, maritialStatusID: Int, relationshipWithMemberId: Int, bloodGroupID: Int, relegionID: Int, nationalityID: Int) async { guard APIManager.shared.isConnectedToInternet else { showInfoToast(message: "No internet connection.") return } let url = APIEndPoint.userSendStaffProfileRequest // 1. 先放必填参数 var params: [String: Any] = [ "titleID": titleID, "maritialStatusID": maritialStatusID, "relationshipWithMemberId": relationshipWithMemberId, "bloodGroupID": bloodGroupID, "relegionID": relegionID, "nationalityID": nationalityID ] // 2. 逐个判断可选字段,非空才加入 if let fName = profile?.fName { params["fName"] = fName } if let mName = profile?.mName { params["mName"] = mName } if let lName = profile?.lName { params["lName"] = lName } if let mobile = profile?.mobile { params["mobile"] = mobile } if let alternateMobile = profile?.alternateMobile { params["alternateMobile"] = alternateMobile } // ... 后面的接口请求逻辑不变 }
这个方案的好处是代码更少,不需要修改TextField的Binding逻辑,适合只要非空就传的场景。
两种方案都能解决你“不传空字符串参数”的问题,方案1更精准匹配你“只传修改过的参数”的需求,方案2更简洁,你可以根据自己的业务场景选~
内容来源于stack exchange
相关产品推荐
相关产品推荐

