如何在SwiftUI中使用Realm

时间:2019-06-19 23:50:44

标签: realm swiftui

我一直试图弄清楚如何在SwiftUI中使用Realm。问题在于SwiftUI和Realm都具有List类型。将SwiftUI导入到Realm模型中以使该类成为BindableObject并尝试创建Realm List属性时,会出现错误。

是否可以使用Realm对象模型的实例并使其在SwiftUI中成为BindableObject?

2 个答案:

答案 0 :(得分:6)

当然,这非常简单,使用模块标识符作为前缀,如下所示:

let members = RealmSwift.List<Member>()

现在到您的问题的第二部分。将Realm对象(或列表或结果集)封装在BindableObject中很容易:

final class DBData: BindableObject  {

    let didChange = PassthroughSubject<DBData, Never>()

    private var notificationTokens: [NotificationToken] = []    
    var posts = Post.all

    init() {
        // Observe changes in the underlying model
        self.notificationTokens.append(posts.observe { _ in
            self.didChange.send(self)
        })

        self.notificationTokens.append(Message.all.observe { _ in
            self.didChange.send(self)
        })
    }
}

如果通过使用DBDataView@ObjectBinding实例“链接”到SwiftUI @EnvironmentObject,则UI将会刷新,并且{{1 }}(在我们的示例中)每次底层领域更改时都可用。

答案 1 :(得分:3)

@JustinMiller我创建了一个ChannelsData类,该类用于侦听Realm集合中聊天通道中的更改。然后,通过在我的视图中将ChannelsData设置为@EnvironmentObject来更新UI。这是在Xcode 11 GM Seed中对我有用的东西:

final class ChannelsData: ObservableObject {
    @Published var channels: [Channel]
    private var channelsToken: NotificationToken?

// Grab channels from Realm, and then activate a Realm token to listen for changes.
init() {
    let realm = try! Realm()
    channels = Array(realm.objects(Channel.self)) // Convert Realm results object to Array
    activateChannelsToken()
}

private func activateChannelsToken() {
    let realm = try! Realm()
    let channels = realm.objects(Channel.self)
    channelsToken = channels.observe { _ in
        // When there is a change, replace the old channels array with a new one.
        self.channels = Array(channels) 
    }
}

deinit {
    channelsToken?.invalidate()
}

然后我使用@EnvironmentObject来获取我的视图的通道:

struct ChannelsContainerView: View {

    @EnvironmentObject var channelsData: ChannelsData

    var body: some View {
        List(channelsData.channels.indexed(), id: \.1.id) { index, _ in
            NavigationLink(destination: ChatView()) {
                ChannelRow(channel: self.$channelsData.channels[index])
            }
        }
    }
}

不用担心列表中的indexed()函数。但是,如果您感到好奇,它来自Majid的聪明方法,可以在此处创建灵活的SwiftUI数据存储类:https://mecid.github.io/2019/09/04/modeling-app-state-using-store-objects-in-swiftui/

如果要从另一个视图进入该视图,请确保将.environmentObject(ChannelsData())添加到视图链接(以及在预览中),否则将无法正常工作。