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

Swift中.onReceive未按预期工作:加载界面无法正常关闭

问题分析与解决方案

核心问题

  1. 类型声明错误:Variables类中AllAirplanes的类型String<Array>是无效语法,正确的字符串数组类型应为[String],错误类型导致@Published无法正常发送更新通知。
  2. 数组更新方式错误:更新AllAirplanes时使用removeAll()+append()的原地修改方式,@Published仅在属性被重新赋值时触发更新,原地修改数组不会改变其引用地址,因此无法触发视图刷新。

修正步骤

1. 修复Variables类的类型声明

class Variables: ObservableObject {
    @Published var AllAirplanes: [String] = [] // 修正为正确的字符串数组类型
}

2. 修改Firebase数据获取逻辑,通过赋值新数组触发更新

@StateObject var v = Variables()

func getAllAirplanes() {
    db.collection("Airplanes")
        .addSnapshotListener { querySnapshot, error in
            guard let documents = querySnapshot?.documents else {
                print("Error fetching documents: \(error!)")
                return
            }
            
            // 用临时数组存储数据,避免原地修改原数组
            var tempAirplanes: [String] = []
            for document in documents {
                print("\(document.documentID) => \(document.data())")
                tempAirplanes.append(document.documentID)
            }
            
            // 移除指定元素
            tempAirplanes.removeAll { $0 == "Simulator" }
            
            // 直接赋值新数组,触发@Published的更新通知
            v.AllAirplanes = tempAirplanes
            
            print(
"""
------------------------------
All Airplanes: \(v.AllAirplanes)
------------------------------
"""
            )
        }
}

3. 优化视图加载逻辑

修复@Published后,视图会自动响应数组变化,推荐使用.onChange替代.onReceive,逻辑更直观:

@EnvironmentObject var v: Variables
@State private var isActiveView = false
@State private var isAnimation = false

var body: some View {
    if !isActiveView {
        VStack {
            // 加载界面内容,比如加载动画或提示文本
            Text("加载中...")
        }
        .onAppear {
            // 视图出现时触发数据获取
            getAllAirplanes()
        }
        .onChange(of: v.AllAirplanes) { newAirplanes in
            // 数组非空时执行跳转逻辑
            guard !newAirplanes.isEmpty else { return }
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
                withAnimation(Animation.easeOut(duration: 1.0)) {
                    isAnimation.toggle()
                }
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 3.8) {
                withAnimation {
                    isActiveView.toggle()
                    locationViewModel.getUserLocation()
                }
            }
        }
    } else {
        // 主界面内容
        MainView()
    }
}

补充说明

原代码中.onReceive仅触发一次,是因为类型错误导致@Published无法正常工作,加上原地修改数组不触发更新通知,视图无法感知数组内容变化。修复类型和更新方式后,@Published会在数组变化时正确通知视图,.onChange就能正常响应所有数组更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:05:39