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

为什么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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 15:27:01