为什么SwiftUI中Publisher已发送值但对应视图未正常渲染?
问题根本原因
你的异常是两个独立的Combine Publisher同时对同一个@Published属性userTextError赋值,存在时序竞争:
usernamevalidation和usernamevalidated都监听$userText的输入变化,当用户输入非空的非法用户名时,两个流会同时触发回调- 正常时序下:
usernamevalidation先执行,判断输入非空所以给userTextError赋值空字符串,随后usernamevalidated判断格式非法,赋值错误提示,错误正常展示 - 异常时序下:
usernamevalidated先赋值错误提示,随后usernamevalidation赋值的空字符串把错误提示覆盖,就会出现错误不展示的问题
另外你的代码还存在一处命名笔误:View中绑定的是passwordText、passwordError,但ViewModel中定义的是userText、userTextError,需要先统一命名避免关联错误。
修复方案
把两个校验逻辑合并为单个Publisher,避免多流赋值冲突,修改后的ViewModel代码如下:
import Combine final class UserViewModel: ObservableObject { private var cancellables = Set<AnyCancellable>() @Published var userText: String = "" @Published var userTextError = "" init(){ $userText .dropFirst() .map { username in // 同一流内顺序处理两种校验逻辑 if username.isEmpty { return "Emptyusername " } if !username.isValidUserName() { return "wrong username " } return "" } .receive(on: DispatchQueue.main) .assign(to: \.userTextError, on: self) .store(in: &cancellables) } }
建议使用
DispatchQueue.main替代RunLoop.main作为接收调度,稳定性更高,能减少不必要的调度异常。
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

