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

SwiftUI中无法从Struct向View返回值 触发void函数非空返回报错

问题根因

你遇到的Unexpected non-void return value in void function报错,以及值无法传递到TextEditor的问题,核心是两个认知错误:

  1. 你写return medicalContent的位置是Firestore网络请求的异步回调闭包内部,这个闭包本身是无返回值(void)类型,不支持return向外传值。异步网络请求不会阻塞代码执行,等请求拿到结果时闭包才会独立运行,return的值只会被丢弃,根本传不到外层的结构体属性上。
  2. 你在闭包内部写了let medicalContent = data["content"] as! String ?? "",这行代码是在闭包作用域里新建了一个和外层@State var medicalContent完全无关的局部常量,你print的是这个局部变量,从来没有给外层的状态属性赋过值,自然TextEditor拿不到数据。

额外说明:你写的as! String ?? ""本身有语法问题,as!是强制转换,一旦data["content"]不是String类型会直接触发崩溃,后面的空值合并运算符根本不会生效。

修复方案

直接修改代码如下:

struct MedicalEdit: View {
    @State var medicalContent: String = ""

    var body: some View {
        TextEditor(text: $medicalContent)
            .onAppear {
                fetchCalmStuff()
            }
    }

    func fetchCalmStuff(){
        // 安全获取用户ID,避免强制解包崩溃
        guard let uid = Auth.auth().currentUser?.uid else { return }
        let db = Firestore.firestore()

        let ref = db.collection("list").document(uid).collection("notes")
        ref.document("medical").setData(["content":"medical content","identity":"medical" ])

        db.collection("userslist").document(uid).collection("Themes").whereField("identity", isEqualTo: "medical")
            .getDocuments() { (querySnapshot, err) in
                if let err = err {
                    print("Error getting documents: \(err)")
                    return
                }
                guard let documents = querySnapshot?.documents else { return }
                for document in documents {
                    let data = document.data()
                    // 安全做类型转换
                    guard let content = data["content"] as? String else { continue }
                    print(content)
                    // 所有UI/状态更新必须切到主线程执行
                    DispatchQueue.main.async {
                        self.medicalContent = content
                    }
                }
        }
    }
}
关键修改点
  • 移除了init中调用fetchCalmStuff的逻辑,改到.onAppear中触发:SwiftUI的视图初始化方法可能被系统多次调用,放在init里会导致重复发起网络请求
  • 删除了回调闭包中错误的return语句:异步回调无法通过return向外传递值,拿到数据后直接更新外层的@State状态变量即可
  • 修正了类型转换的错误写法:用as? String做可选转换,避免强制解包导致的崩溃
  • 状态更新逻辑包裹在DispatchQueue.main.async中:Firestore的回调默认在后台线程执行,所有和UI相关的状态修改必须切换到主线程,否则会触发运行时警告甚至异常
  • 移除了闭包内部和状态属性重名的局部变量定义,避免作用域混淆导致赋值失败

内容的提问来源于stack exchange,提问作者alex

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 16:18:20