Closed7
SwiftUIとRealm
SwiftUIに合う書き方が記載されていたのでこちらを見ていく
概要
リストデータを管理するアプリのSample
ItemsView
アイテム一覧View
追加・削除・並び替えができる
ItemDetailsView
アイテムをタップしたときに表示される詳細View
アイテム名の変更とお気に入り登録ができる
モデル定義
Persisted
というPropertyWrapperが用意されている
primaryKey: true
とするとプライマリーキーになる
/// An individual item. Part of a `Group`.
final class Item: Object, ObjectKeyIdentifiable {
/// The unique ID of the Item. `primaryKey: true` declares the
/// _id member as the primary key to the realm.
@Persisted(primaryKey: true) var _id: ObjectId
/// The name of the Item, By default, a random name is generated.
@Persisted var name = "\(randomAdjectives.randomElement()!) \(randomNouns.randomElement()!)"
/// A flag indicating whether the user "favorited" the item.
@Persisted var isFavorite = false
/// The backlink to the `Group` this item is a part of.
@Persisted(originProperty: "items") var group: LinkingObjects<Group>
}
/// Represents a collection of items.
final class Group: Object, ObjectKeyIdentifiable {
/// The unique ID of the Group. `primaryKey: true` declares the
/// _id member as the primary key to the realm.
@Persisted(primaryKey: true) var _id: ObjectId
/// The collection of Items in this group.
@Persisted var items = RealmSwift.List<Item>()
}
Sampleアプリはこんな構成
@main
struct ContentView: SwiftUI.App {
var body: some Scene {
WindowGroup {
LocalOnlyContentView()
}
}
}
struct LocalOnlyContentView: View {
// Implicitly use the default realm's objects(Group.self)
@ObservedResults(Group.self) var groups
var body: some View {
if let group = groups.first {
// Pass the Group objects to a view further
// down the hierarchy
ItemsView(group: group)
} else {
// For this small app, we only want one group in the realm.
// You can expand this app to support multiple groups.
// For now, if there is no group, add one here.
ProgressView().onAppear {
$groups.append(Group())
}
}
}
}
@ObservedResults
を利用するとView表示時にDefaultのRealmを利用してロードしてくれる
また監視対象になるため変更があった場合にViewが更新される
@ObservedResults(MyObject.self, keyPaths: ["myList.property"])
こうすることで通知対象を絞ることも可能
struct ItemsView: View {
/// The group is a container for a list of items. Using a group instead of all items
/// directly allows us to maintain a list order that can be updated in the UI.
@ObservedRealmObject var group: Group
/// The button to be displayed on the top left.
var leadingBarButton: AnyView?
var body: some View {
NavigationView {
VStack {
// The list shows the items in the realm.
List {
ForEach(group.items) { item in
ItemRow(item: item)
}.onDelete(perform: $group.items.remove)
.onMove(perform: $group.items.move)
}.listStyle(GroupedListStyle())
.navigationBarTitle("Items", displayMode: .large)
.navigationBarBackButtonHidden(true)
.navigationBarItems(
leading: self.leadingBarButton,
// Edit button on the right to enable rearranging items
trailing: EditButton())
// Action bar at bottom contains Add button.
HStack {
Spacer()
Button(action: {
// The bound collection automatically
// handles write transactions, so we can
// append directly to it.
$group.items.append(Item())
}) { Image(systemName: "plus") }
}.padding()
}
}
}
}
ItemViewは@ObservedRealmObject
としてgroupを受け取る
そうすると書き込みに応じてトランザクションを自動的に開いてくれる。便利
ItemRowとItemDetailsViewは@ObservedRealmObjectとしてItemを受け取っている
/// Represents an Item in a list.
struct ItemRow: View {
@ObservedRealmObject var item: Item
var body: some View {
// You can click an item in the list to navigate to an edit details screen.
NavigationLink(destination: ItemDetailsView(item: item)) {
Text(item.name)
if item.isFavorite {
// If the user "favorited" the item, display a heart icon
Image(systemName: "heart.fill")
}
}
}
}
/// Represents a screen where you can edit the item's name.
struct ItemDetailsView: View {
@ObservedRealmObject var item: Item
var body: some View {
VStack(alignment: .leading) {
Text("Enter a new name:")
// Accept a new name
TextField("New name", text: $item.name)
.navigationBarTitle(item.name)
.navigationBarItems(trailing: Toggle(isOn: $item.isFavorite) {
Image(systemName: item.isFavorite ? "heart.fill" : "heart")
})
}.padding()
}
}
このスクラップは2022/02/20にクローズされました