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

如何让Realm与SwiftUI List(children:)实现层级列表展示?

问题:SwiftUI List层级展示Realm父子关系数据失败

尝试用Realm构建父子关系数据,并通过SwiftUI List的children:初始化器实现层级展示(带展开箭头)。已完成无父节点列表展示,但在适配children:参数时遇到类型转换问题。

Realm模型类定义

import Foundation
import RealmSwift
    
class BlockList: RealmSwift.Object, RealmSwift.ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var id: RealmSwift.ObjectId
    @Persisted var title: String
    @Persisted var childBlockLists = RealmSwift.List<BlockList>()
    @Persisted(originProperty: "childBlockLists") var parentBlockList: RealmSwift.LinkingObjects<BlockList>
    
    convenience init(title: String) {
        self.init()
        self.title = title
   }
}

ContentView代码

struct ContentView: View {
    @ObservedResults(BlockList.self) var blockLists
    
    var body: some View {
        let parentBlockLists = blockLists.where {
            ($0.parentBlockList.count == 0)
        }
        
        List(parentBlockLists) { blockList in
            Text(blockList.title)
        }
        .toolbar {
            ToolbarItem {
                Button(action: addItem) {
                    Label("Add Item", systemImage: "plus")
                }
            }
        }
    }
    
    func addItem() {
        let realm = try! Realm()

        let newBlockList = BlockList(title: "New List")
        let newSubBlockList = BlockList(title: "New SubList")
        newBlockList.childBlockLists.append(newSubBlockList)
        try! realm.write {
            realm.add(newBlockList)
        }
    }
}

尝试的扩展及错误

为适配children:参数,尝试扩展BlockList转换子节点类型,但报错:

extension BlockList {
    var childBlockListsArray: AnyRealmCollection<BlockList> {
        AnyRealmCollection(childBlockLists)
    }
}

Key path value type 'AnyRealmCollection' cannot be converted to contextual type 'AnyRealmCollection?'

询问如何正确提供Realm数据及其子节点键路径以实现层级展示。


解决方案

1. 调整子节点属性的可选类型

SwiftUI List的children:参数要求子节点路径的类型是可选的集合类型(因为可能没有子节点),所以需要把扩展属性改为返回AnyRealmCollection<BlockList>?,空集合时返回nil:

extension BlockList {
    var children: AnyRealmCollection<BlockList>? {
        // 当子列表为空时返回nil,否则包装为AnyRealmCollection
        childBlockLists.isEmpty ? nil : AnyRealmCollection(childBlockLists)
    }
}

2. 使用List的层级初始化器

修改ContentView中的List实现,使用List(children:)初始化器,传入父节点集合和子节点的键路径:

struct ContentView: View {
    @ObservedResults(BlockList.self) var blockLists
    
    var body: some View {
        let parentBlockLists = blockLists.where {
            $0.parentBlockList.count == 0
        }
        
        // 使用children参数指定子节点键路径
        List(parentBlockLists, children: \.children) { blockList in
            Text(blockList.title)
        }
        .toolbar {
            ToolbarItem {
                Button(action: addItem) {
                    Label("Add Item", systemImage: "plus")
                }
            }
        }
    }
    
    func addItem() {
        let realm = try! Realm()

        let newBlockList = BlockList(title: "New List")
        let newSubBlockList = BlockList(title: "New SubList")
        newBlockList.childBlockLists.append(newSubBlockList)
        try! realm.write {
            realm.add(newBlockList)
        }
    }
}

关键说明

  • AnyRealmCollection是Realm提供的可观察集合类型,能和SwiftUI的ObservedResults配合实现自动更新
  • 必须返回可选类型(?),因为当节点没有子元素时,List需要隐藏展开箭头
  • 直接使用\.children键路径即可,无需手动转换数组类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 05:50:37