Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ /

响应更改 - SwiftUI

在此页面上

  • 观察对象
  • 观察查询结果
  • 对观察结果排序
  • 观察分节结果
  • 观察应用程序状态

Swift SDK提供了 @ObservedRealmObject属性包装器,该包装器可在观察到的对象发生更改时使视图失效。 您可以使用此属性包装器创建一个视图,该视图在观察到的对象发生更改时自动更新。

struct DogDetailView: View {
@ObservedRealmObject var dog: Dog
var body: some View {
VStack {
Text(dog.name)
.font(.title2)
Text("\(dog.name) is a \(dog.breed)")
AsyncImage(url: dog.profileImageUrl) { image in
image.resizable()
} placeholder: {
ProgressView()
}
.aspectRatio(contentMode: .fit)
.frame(width: 150, height: 150)
Text("Favorite toy: \(dog.favoriteToy)")
}
}
}

Swift SDK 提供了@ObservedResults属性包装器,可让您观察查询结果的集合。 您可以对 ObservedResults 集合执行快速写入,并且当观察到的查询发生更改时,视图会自动更新。 例如,您可以使用 onDelete从观察到的狗列表中删除一条狗。

注意

@ObservedResults 属性包装器用于“SwiftUI 视图”。如果您想观察视图模型中的结果,请注册更改监听器

struct DogsView: View {
@ObservedResults(Dog.self) var dogs
/// The button to be displayed on the top left.
var leadingBarButton: AnyView?
var body: some View {
NavigationView {
VStack {
// The list shows the dogs in the realm.
// The ``@ObservedResults`` above implicitly opens a realm and retrieves
// all the Dog objects. We can then pass those objects to views further down the
// hierarchy.
List {
ForEach(dogs) { dog in
DogRow(dog: dog)
}.onDelete(perform: $dogs.remove)
}.listStyle(GroupedListStyle())
.navigationBarTitle("Dogs", displayMode: .large)
.navigationBarBackButtonHidden(true)
.navigationBarItems(
leading: self.leadingBarButton,
// Edit button on the right to enable rearranging items
trailing: EditButton())
}.padding()
}
}
}

提示

另请参阅:

有关 Realm 支持的查询语法和查询类型的更多信息,请参阅:读取 - Swift SDK筛选数据 - Swift SDK

@ObservedResults属性包装器可以采用SortDescriptor参数对查询结果进行排序。

struct SortedDogsView: View {
@ObservedResults(Dog.self,
sortDescriptor: SortDescriptor(keyPath: "name",
ascending: true)) var dogs
var body: some View {
NavigationView {
// The list shows the dogs in the realm, sorted by name
List(dogs) { dog in
DogRow(dog: dog)
}
}
}
}

提示

您不能将计算属性用作 @ObservedResultsSortDescriptor

10.29.0 版中的新增功能

您可以观察结果集,该结果集通过从对象属性生成的键划分为多个部分。我们在模型中添加了一个计算变量,但这个变量并不持久存在;我们只是用它来对结果集进行分区。

var firstLetter: String {
guard let char = name.first else {
return ""
}
return String(char)
}

然后我们可以使用 @ObservedSectionedResults 属性包装器来观察根据计算变量键划分的结果集。

@ObservedSectionedResults(Dog.self,
sectionKeyPath: \.firstLetter) var dogs

您可以使用这些观察到的分节结果来填充按节划分的“列表”视图:

struct SectionedDogsView: View {
@ObservedSectionedResults(Dog.self,
sectionKeyPath: \.firstLetter) var dogs
/// The button to be displayed on the top left.
var leadingBarButton: AnyView?
var body: some View {
NavigationView {
VStack {
// The list shows the dogs in the realm, split into sections according to the keypath.
List {
ForEach(dogs) { section in
Section(header: Text(section.key)) {
ForEach(section) { dog in
DogRow(dog: dog)
}
}
}
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Dogs", displayMode: .large)
.navigationBarBackButtonHidden(true)
.navigationBarItems(
leading: self.leadingBarButton,
// Edit button on the right to enable rearranging items
trailing: EditButton())
}.padding()
}
}
}

如果您的应用使用Atlas Device Sync ,您可以观察应用程序对象对登录状态更改的React 。 这样,您的应用就能在有app.currentUser的情况下执行操作,或者在没有app.currentUser的情况下引导用户登录。

由于 Realm 会在设备上缓存用户凭据,因此应用可以在具有 app.currentUser 的情况下离线运行。

/// This view observes the Realm app object.
/// Either direct the user to login, or open a realm
/// with a logged-in user.
struct FlexibleSyncContentView: View {
// Observe the Realm app object in order to react to login state changes.
@ObservedObject var app: RealmSwift.App
var body: some View {
if let user = app.currentUser {
// Create a `flexibleSyncConfiguration` with `initialSubscriptions`.
// We'll inject this configuration as an environment value to use when opening the realm
// in the next view, and the realm will open with these initial subscriptions.
let config = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
let peopleSubscriptionExists = subs.first(named: "people")
let dogSubscriptionExists = subs.first(named: "dogs")
// Check whether the subscription already exists. Adding it more
// than once causes an error.
if (peopleSubscriptionExists != nil) && (dogSubscriptionExists != nil) {
// Existing subscriptions found - do nothing
return
} else {
// Add queries for any objects you want to use in the app
// Linked objects do not automatically get queried, so you
// must explicitly query for all linked objects you want to include.
subs.append(QuerySubscription<Person>(name: "people"))
subs.append(QuerySubscription<Dog>(name: "dogs"))
}
})
OpenFlexibleSyncRealmView()
.environment(\.realmConfiguration, config)
} else {
// If there is no user logged in, show the login view.
LoginView()
}
}
}

后退

配置并打开 Realm