SwiftUI中无法从Struct向View返回值 触发void函数非空返回报错
问题根因
你遇到的Unexpected non-void return value in void function报错,以及值无法传递到TextEditor的问题,核心是两个认知错误:
- 你写
return medicalContent的位置是Firestore网络请求的异步回调闭包内部,这个闭包本身是无返回值(void)类型,不支持return向外传值。异步网络请求不会阻塞代码执行,等请求拿到结果时闭包才会独立运行,return的值只会被丢弃,根本传不到外层的结构体属性上。 - 你在闭包内部写了
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
相关产品推荐
相关产品推荐

