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

使用RealmSwift与SwiftUI在当前视图修改记录且不返回上级导航

问题解决:Realm视图修改数据不返回上级且实时刷新

核心问题

通过@ObservedResults从Realm获取订单对象后,在详情页(OrderView)执行删除订单项操作时,会自动返回上级导航视图,同时需要实现数据修改后视图实时同步刷新。想知道如何将已存储的Realm对象转为@StateRealmObject,以及更优的实现方案。

最优实现方案

核心思路是用@StateRealmObject直接持有当前订单对象,替代通过@ObservedResults二次查询的方式,同时修正Realm写入逻辑,避免父视图因集合更新导致的重绘跳转。

步骤1:修改OrderView,使用@StateRealmObject

直接在详情页持有订单对象,无需通过ID再次查询,同时利用@StateRealmObject的自动监听特性实现视图实时刷新:

struct OrderView: View {
    // 用@StateRealmObject持有当前订单,自动监听对象变化
    @StateRealmObject var currentOrder: Order

    // 初始化直接传入解冻后的订单对象
    init(currentOrder: Order) {
        self._currentOrder = StateRealmObject(wrappedValue: currentOrder)
    }

    func deleteOrderLine(id: String, sku: String) {
        guard let realm = currentOrder.realm else { return }
        do {
            try realm.write {
                // 直接从当前订单的订单项列表中查找并删除
                let lineToDelete = currentOrder.orderLineId.first {
                    $0.id == id && $0.productSku == sku
                }
                if let line = lineToDelete {
                    realm.delete(line)
                }
            }
        } catch {
            print("删除订单项失败:\(error)")
        }
    }

    var body: some View {
        // 展示订单数据,遍历currentOrder.orderLineId
        List(currentOrder.orderLineId) { line in
            HStack {
                Text(line.productSku)
                Spacer()
                Button("删除") {
                    deleteOrderLine(id: line.id, sku: line.productSku)
                }
                .foregroundColor(.red)
            }
        }
        .navigationTitle(currentOrder.name)
    }
}

步骤2:修改父视图OrderListView2,直接传递解冻后的对象

避免传递ID再查询,直接将解冻后的订单对象传给详情页,减少不必要的Realm查询,同时避免父视图集合更新导致的跳转:

struct OrderListView2: View {
    @ObservedResults(Order.self) var allOrders

    var body: some View {
        NavigationStack { // iOS 16+用NavigationStack,旧版本用NavigationView
            List(allOrders.sorted(byKeyPath: "dateCreated", ascending: false)) { order in
                // 传递解冻后的订单对象给详情页
                NavigationLink(destination: OrderView(currentOrder: order.thaw()!)) {
                    Text(order.name)
                }
            }
            .navigationTitle("订单列表")
        }
    }
}

关键说明

  • 为什么之前会返回上级?
    父视图的allOrders是@ObservedResults,当子视图删除订单项后,订单对象的orderLineId列表发生变化,触发allOrders更新,父视图的List会重新渲染,导致NavigationLink被重建,从而回到上级页面。用@StateRealmObject持有单个对象后,子视图的依赖是单个对象,父视图的集合更新不会影响子视图的导航状态。
  • @StateRealmObject的作用
    自动监听Realm对象的变化,当对象的属性或关联列表修改时,会自动触发视图刷新;同时持有对象的强引用,保证对象在视图生命周期内有效。
  • 解冻对象的必要性
    @ObservedResults返回的是冻结对象(Frozen Objects),无法直接修改,所以需要调用thaw()获取可写入的对象实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:20:28