見出し画像

SwiftUIでいこう! - RealmをSPMで使う。

SPMでRealmを取り込みSWiftUIでデータベースを使ったメモ機能を実装します。参考サイトをみながらコードを書いてみます。基本的にCocoaPodsで導入して実装する方法と同じですがSPMだと使い方が簡単で間違えることはほぼないと思います。

XcodeのSPMで導入で必要なGitHubのRealmのサイトのURL(以下のURL)をXcodeのSPMに入力してライブラリを導入します。

CocoaPodsでインストールすることを考えると随分簡単に導入できます。

今回の参考動画でちょっと気になったプロパティラッパー@StateObjectの参考サイトです。

必要なコードを分類します。

・表示部分は、"HomeViiew","AddPageView"。
・Viewを作るためにモデルは、"DBViewModel"。
・データベースに入れるデータを定義する"Card"

それぞれ作って最終的にはHomeViewをContentViewに集約(HomeViewを配置)する形になります。

まずメインで表示の役割をもつHomeViewの構造ですが、

struct HomeView: View {
   @StateObject var modelData = DBViewModel()
   
   var body: some View {
       NavigationView{
           ScrollView{
               VStack(spacing:15){
                   ForEach(modelData.cards){card in
                       VStack(alignment: .leading, spacing: 10, content: {
                           Text(card.title)
                           Text(card.detail)
                               .font(.caption)
                               .foregroundColor(.gray)
                       })
                       .frame(maxWidth: .infinity,alignment:.leading)
                       .padding(10)
                       .background(Color.gray.opacity(0.15))
                       .cornerRadius(10)
                   }
               }
               .padding()
               
           }
           .navigationTitle("Realm")
           .toolbar{
               ToolbarItem(placement: .navigationBarTrailing){
                   Button(action: {modelData.openNewPage.toggle()}){
                       Image(systemName: "plus")
                           .font(.title2)
                   }
               }
          }
           .sheet(isPresented: $modelData.openNewPage, content: {
               AddPageView()
                   .environmentObject(modelData)
           })
       }
   }
}

 NavigationView、ScrollView、 VStackで縦に並べたものをスクロールできるようにします。

.toolbar{
ToolbarItem(placement: .navigationBarTrailing){
Button(action: {modelData.openNewPage.toggle()}){
Image(systemName: "plus")
.font(.title2)
}
}
}
.sheet(isPresented: $modelData.openNewPage, content: {
AddPageView()
.environmentObject(modelData)

の部分で"+"ボタンを押すと下から入力部分であるAddPageView()のsheetが出てくるようにしています。

ボタンを押すと出てくるもう一つのView、AddPageView()ですが

struct AddPageView: View {
   @EnvironmentObject var modelData:DBViewModel
   @Environment(\.presentationMode) var presentation
   
   var body: some View {
     NavigationView{
           List{
               Section(header: Text("Title")){
                   TextField("",text:$modelData.title)
               }
               Section(header: Text("Detail")){
                   TextField("",text:$modelData.detail)
               }
           }
           .listStyle(GroupedListStyle())
           .navigationTitle("Add Data")
           .navigationBarTitleDisplayMode(.inline)
           .toolbar{
               ToolbarItem(placement: .navigationBarTrailing){
                   Button(action: {modelData.addData()},label:{
                       Text("Done")
                   })
               }
               
               ToolbarItem(placement: .navigationBarLeading){
                   Button(action: {presentation.wrappedValue.dismiss()},label:{
                       Text("Cancel")
                   })
               }
           }
       }
   }
}

この2つのViewで実際のデータは

@StateObject var modelData = DBViewModel()
@EnvironmentObject var modelData:DBViewModel

どちらも、変数modelDataDBViewModel型のデータを入れて実際の表示をさせていきます。

class DBViewModel:ObservableObject{
   
   @Published var title = ""
   @Published var detail = ""
   @Published var openNewPage = false
   @Published var cards:[Card] = []
   
   init(){
       fetchData()
   }
   
   func fetchData(){
       guard let dbRef = try? Realm() else {return }
       let results = dbRef.objects(Card.self)
       self.cards = results.compactMap({(card)->Card? in
           return card
       })
   }
   
   func  addData(){
       let card = Card()
       card.title = title
       card.detail = detail 
       guard let dbRef = try? Realm() else {return }
       try? dbRef.write{
           dbRef.add(card)
       } 
       fetchData()
   }
}

その実際のデータはRealmで管理します。

@Published var cards:[Card] = []

の部分でコントロールします。"Card"は以下で定義します。

import SwiftUI
import RealmSwift

class Card:Object,Identifiable{
   @objc dynamic var id:Date = Date()
   @objc dynamic var title = ""
   @objc dynamic var detail = ""
}

realmの基本的な使い方のついては以下で書いています。


この記事が気に入ったらサポートをしてみませんか?