REALMSWIFTを使用したCRUD操作パート1

このパートでは、次のことをカバーします:

  1. Realmとは何ですか
  2. Realmswift
  3. 複雑なレルムモデルを作成する
  4. @objcとdynamicをプロパティで使用する理由
  5. Realmで一対一と多の関係
  6. Realmにカスタムenumを格納する方法
  7. RealmOptionalとは何であり、Swift Optional Atomic Propertyを格納する方法
  8. 計算されたプロパティは、realmで一時的なプロパティとして動作する方法
  9. パフォーマンス向上のためにインデックスを作成する方法
  10. レルム内のオブジェクトをリンクしているもの
  11. 複雑な述語クエリ
  12. crud操作
  13. レルム内のライブ結果とは何ですか
  14. Realmオブジェクトの変更

Realmは、クロスプラットフォームのモバイルオブジェクトデータベースです。 Core DataやSqliteと比較して、非常に高速で、パフォーマンスが高く、使いやすいです。 バックエンドとしてSqliteを使用するCore Dataと比較して、ストレージメカニズムを使用してオブジェクトをJSONとしてディスクに格納します。 これはクロスプラットフォームのC++で書かれているので、Android、iOS、macOS、または他のプラットフォームでもまったく同じように動作します。

RealmSwift

Realmのほとんどはオープンソースですが、Realmのプラットフォームの背後にある秘密のソースは、c++でゼロから書かれたコアDBエンジンです。 RealmSwiftはObjective-C Realm frameworkのラッパーであり、Objective-C Realm frameworkはRealm Core DBエンジンのラッパーです。

はじめに

このチュートリアルでは、図1に示すように、これらのモデルに取り組んでいきます

ユーザー→それはモデルがuserId また、passportモデルとのTo-one関係とTodoタスクとのTo-Many関係もあります。 (ユーザーはpassportのみを持ち、多くのtodoタスクを持つことができます)

Passport→ユーザーのpassport情報を含むモデルであり、UserUserオブジェクトの逆バックリンクもあります。div>

ユーザーモデル

図2に示すように、ユーザーモデルを作成し、いくつかのプロパティを追加します。

  1. まず、ObjectUserRealm Object。 Realmオブジェクトは基本的に標準データモデルであり、アプリで定義した他の標準データモデルと同様です。 唯一の違いは、それらがレルムの永続性と能力に裏打ちされていることです。 すべてのObjectクラスRealmを調べることで、スキーマを推測できます。 永続化するすべてのモデルは、Objectクラスから継承する必要があります。li>
  2. firstNameStringRealmSwiftは、String、Date、DataなどのObjective-C Realmフレームワーク型のラッパーであるため、Objective-CのNSObjectのサブクラスなので、Swiftのオブジェクト型も考慮することができます。 この@objcに加えて、Swiftコード(クラス、メソッド、プロパティなど)が必要なことを意味します。)objective-Cから見えるようにするには、dynamicはObjective-C dynamic dispatchを使用することを意味します。 データベースレルムで簡単なswiftオブジェクトストアを作成するには、objective-C動的ディスパッチ機能を使用してフードの下で作業を行います
  3. userIduserId primarykey主キーを作成します。 このメソッドのデフォルトの実装はnilを返します。 注意userId は、客観的なCレルムのラッパーであるため、客観的なCプリミティブInt型として機能します
  4. passportプロパティは、別のレルムオブ 私たちは、パスポートモデルとのTo-One関係を作成しました。 あるrealmオブジェクトが別のrealmオブジェクトを指している関係/オブジェクトへのリンク。 別のRealmオブジェクトとのリレーションシップを作成する場合、そのプロパティの型は省略可能でなければなりません。 パスポートの変数ポインタ参照では、Passportオブジェクトは
  5. privateUserTypeUserTypeUserTypeはswift enumなので、Realmに直接格納することはできません。 すべてのcase値には、caseの名前と一致する暗黙的に割り当てられた生の値があります。 この生の値を使用して、EnumオプションをRealmでIntとして永続化します。 しかし、クライアントは計算された列挙型プロパティにアクセスしており、内部の列挙型の生の値/原子値は、クライアントには表示されないデータベースに格納されています。
  6. 文字列、NSDate、およびNSDataプロパティは、標準のSwift構文を使用して、オプションまたは非オプションとして宣言できます。オプションの数値型は、RealmOptionalを使用して宣言されます。 RealmSwiftはObjective C Realmのラッパーであり、Objective CにはオプションのIntがないため、RealmはこのシナリオでRealmOptional型を作成しました。 すべてのObjective Cプリミティブ型は、Optionalを使用してSwiftで必要とするRealmOptionalを使用する必要があります。 これは、動的プロパティの動的ディスパッチに使用されるObjective Cランタイムではジェネリックプロパティを表すことができず、常にletで宣言する必要があ Realmクラスなので、Realm persistオブジェクトが持っているすべての機能を持っています。 図2に示すように、isEmailSubscriptionEnableRealmOptionalBoolは、参照型であるため、letで使用したnilであり、将来アドレスを変更したくないこ
  7. 図2に示すように、ユーザーはRealm Todoオブジェクトのコレクションである多くのtodoを持つことができます。 Realmオブジェクトインスタンスのコレクションを保持するRealmクラスとしてリストします。 Todoモデルと多対多の関係を作成しました。 1つのrealmオブジェクトがrealmオブジェクトのコレクションを指すto-manyリレーションシップ。 通常のSwift配列を使用してオブジェクトのレルムコレクションを格納すると、例外が発生します。 注:RealmOptional Listのように、すべての組み込み機能を持つRealmクラスなので、動的および@objcキーワードとして宣言することはできません。 Listは、組み込みメソッドやインデックス付き添字を使用したオブジェクトへのアクセスのためのArrayと非常によく似ています。 あなたが見るようにリストが入力され、すべてのオブジェクトが同じタイプでなければなりません
  8. isUserHasTodosは計算されたswiftプロパティであり、ユーザーが行うかどうかのタスクがある場合に返されるレルムデータベースには格納されません。
  9. 最後に、インデックス付きプロパティとしてuserIdfirstNameindexedProperties静的メソッドをオーバーライドすることにより、文字列形式のプロパティの配列を提供します。 データベースをフィルタリングまたはクエリするときのアクセス時間を改善するために、プロパティにインデックスを付けます

図2

passport model

図3に示すように、いくつかのプロパティを持つpassportモデルを作成しました

  1. passportNumberexpiryDate@objcdynamicキーワードを使用して、レルムにフードマジックの下であなたのことを伝える
  2. passportUserUserpassportオブジェクト参照を持っている我々は、passportオブジェクトはまた、このパスポートを持っているユーザーを知っているかどうか、このpassportに関連付けられているユーザーへの参照を持っています。 つまり、PassportにofUserプロパティを作成し、Passportオブジェクトを割り当てるすべてのユーザーオブジェクトの参照を持つPassportにpassportプロパティ。 コアデータでは、それは逆関係と呼ばれています。 その動的なコレクションは、現在のオブジェクトにリンクする人を示します。

Figure 3

As shown in Figure 4 we created Todo Realm model with has a backlink to the all the users pointing to particular task .div>

モデル/スキーマの作成が完了し、実際のcrud操作を行う時間が来ました

オブジェクトをレルムに追加

最初に概念をクリアし、レルムにオブジェク Realmインスタンスを介してデータベースにアクセスできる唯一の方法。 Realmインスタンス(“A Realm”とも呼ばれます)は、レルムデータベースを表します。レルムは、ディスク(init(path:)ConfigurationRealmインスタンスはスレッドセーフではなく、スレッド間で共有したり、キューをディスパッチしたりすることはできません。 Realmにアクセスするスレッドごとに、新しいインスタンスを構築する必要があります。新しいアプリであり、データベースにオブジェクトが格納されていないため、図5に示すようにrealm.isEmptyは、コンソールに印刷されたようにデータベースが空であることを意味します

図5

図6に示すように、タスクの数を実行しました

  1. Realmデータベース
  2. 作成されたRealmデータベース
  3. 作成されたRealm
  4. 作成されたRealm
  5. 作成されたRealm
  6. 作成されたPassporttodos
  7. 作成しましたUserオブジェクトとそれにpassportとtodosを割り当てます。 この初期化されたRealmオプションのプロパティに加えて、isEmailSubscriptionEnableUsertypeゴールドメンバーシップを持つenum

図6に示すように、realmデータベース Realmオブジェクト(User,Passport,Todo)は、通常のSwiftオブジェクトと同様に、アンマネージオブジェクト(つまり、まだRealmに追加されていない)としてインスタンス化して使用することができます。 これらのオブジェクトをレルムで管理するには、レルムに追加する必要があります

図6
図6
図6
図6

図7に示すように、最終的にrealmデータベースにオブジェクトを挿入します。 DBへのカスケード挿入を実行しました。

注意:オブジェクトへのすべての変更(追加、変更、削除)は、書き込みトランザクション内で行う必要があります。Realmの書き込み操作は、非同期ではなく、同期的でブロック的なものです。 スレッドAが書き込み操作を開始した場合、スレッドBはスレッドAが終了する前に同じレルムで書き込み操作を開始します。 書き込み操作は常に自動的に更新されるため、競合状態は作成されません。 書き込み操作は、ディスク領域が不足しているようなエラーをスローする可能性があります

  1. レルムにUserを追加しました。passportとtodosを参照しているため、これらのオブジェクトもレルムに追加されます。
  2. アンマネージオブジェクトをrealmに追加することで、これらのオブジェクトをコンソールに示すように管理しました。 これで、passportはUserオブジェクトにもアクセスできます。 これでデータベースは空になりません
  3. write transactionブロックに追加する必要があるオブジェクトを挿入し、Realmインスタンスのaddメソッドを使用してrealmに追 ここで、userId = 1 を持つユーザーの同じ主キーを持つ別の別のオブジェクトをレルムに別のオブジェクトとして追加しようとすると、例外がトリガーされます

図7

オブジェクトの物理的なストアを確認

デバッガ出力でこのコマンドを実行すると、データが格納されているレルムファイルのアドレスが取得されます

図8

オープン

オープン

オープン

オープン

オープン

オープンdefault.realm

realm studioの
realm studioは、realmデータベースとrealmプラットフォームを簡単に管理できるように構築されたpremiere開発者ツールです。 Realm Studioを使用すると、ローカルおよび同期されたRealmを開いて編集したり、任意のRealm Object Serverインスタンスを管理したりすることができます。 Mac、Windows、またはLinux用に今すぐダウンロードしてください。div>

図9

図10に示すように、実際に格納されたデータ。 あなたは疑問に思うかもしれませんArticlePerson私のプロジェクトクラスの中にはモデルを作成す アプリケーションが実行されると、Realmはアプリとフレームワークのすべてのクラスをイントロスペクトし、RealmのObjectクラスをサブクラス化するクラスを見つけます。 これらのクラスのリストは、ディスクまたはメモリ内に永続化されるデータスキーマであると見なされます。div>

レルムからオブジェクトをフェッチ

レルムからすべてのユーザーレコードをフェッチするプロセスは、次のタスクを持っています

  1. レルムデータベースのインスタンスを取得し、それがスローすることができます:anNSErrorinit()を呼び出すと作成されます
  2. レルムに格納されている指定された型のすべてのオブジェクdiv>

図11

ユーザーをフェッチしました インデックス付きプロパティでもある主キーからのレコードなので、この主キーを持つオブジェクトが存在しない可能性があるため、オプショ 主キーはIntStringString.レルムデータベース内の特定のオブジェクトを一意主キー値が特定のオブジェクトに設定されると、それを変更することはできません。div>

図12
図12
図12

示されているように、いくつかの述語を使用してフィルタリングしました。

  1. フィルタ→に等しい値に一致します
  2. フィルタ大文字と小文字を区別しません→に等しい値に一致します大文字と小文字を区別しません
  3. {1,2,3}フィルタ→値のリストから値に一致します。
  4. filter→firstNameの値がaで始まる場合に一致します。
  5. filter→firstName value conatinsがliの場合に一致します。
  6. Passportオブジェクトを持つ述語passport number==’pass1’を持つユーザーをフィルタリングしたい
  7. Todosオブジェクトを持つ述語tdodo contains details==’Need ot create RxSwift blog’を持つユーザーをフィルタリングしたい

高度なクエリについては、https://academy.realm.io/posts/nspredicate-cheatsheet/https://academy.realm.io/posts/nspredicate-cheatsheet/https://academy.realm.io/posts/nspredicate-cheatsheet/https://academy.realm.io/posts/nspredicate-cheatsheet/https://academy.realm.io/posts/nspredicate-cheatsheet/https://academy.realm.io/posts/nspredicate-cheatsheet/nspredicate cheatsheet

注:”一時的な(計算された)プロパティ”と呼ばれるものは、レルムは”無視されたプロパティ”と呼ばれます。 これらはほとんどの場合、Realmによって無視されるプロパティなので、dbファイルに保存されず、書き込みトランザクションの外部で変更することがでただし、これはまた、クエリなどの無視されないプロパティの多くの機能の恩恵を受けないことを意味します。 (querying for Realm objects can only be done with non-computed, Realm-persisted properties)

Figure 13

As shown in Figure 14 we sorted results with the firstName property on User model

Figure 14

ライブ結果

Realmセクションからのフェッチに関する最後のトピック

Realm結果セットは常に最新の最新データを返します。 結果のデータは古くなることはありません。 これは、ディスクから結果をリロードしたり、何らかの方法でメモリ内のデータを手動で更新したりする必要がないことを意味します。

図15に示すように、新しいユーザーを取得し、realm.objects メソッドを使用してフェッチしませんでした代わりに、新しく追加されたオブジェク コアデータの背景から来た場合は、スタックからオブジェクトを再度取得する必要があります

読み取りと書き込みは、プロジェ Realmオブジェクトは常に最新のものであるため、アプリ内の各クラスはビジネスロジックに焦点を当て、古いデータやキャッシュされたデータの概念を忘div>

図15

レルム上のオブジェクトを変更

図16に示すように、主キーを変更しており、”主キーはオブジェクトが挿入された後に変更できません。”主キーを更新できないため例外です。 Realm Docsから主キーがレルムに追加された場合、主キーは変更できません。 回避策→オブジェクトを削除して再挿入するか、stackoverflowでこの質問を参照してください

図16

図17に示すように、write transactionブロックの外部でrealmからフェッチされたオブジェクトを変更することはできませんこの外部で変更しようとすると、rlmrealmインスタ”

Figure 17

As shown in Figure 18 as we modify object in write transaction block it will persist that object into the disk as well as shown in Figure 19 default.realm file now has a updated firstName value of User

Div>

図19

最後の例は、我々はnewuserでユーザーを更新するために、次のタスクを実行する非常に興味深いです

  1. 私たちは、その主キーuserIdこれは1です
  2. 同じ主キーを持つ新しいUserを作成しました
  3. 書き込みトランザクションでadd batchを呼び出します update=trueを使用したupdateメソッド主キー=1を持つユーザーを更新します。 If update = false it will throw an exception since two objects can’t have same primary key as shown in Figure 20 and 21

Figure 20

Figure 21

Delete Object From Realm

Any objects currently 削除されたものにリンクすると、linkingプロパティがnilに設定されます。 これらのオブジェクトがリストのプロパティからリンクされている場合、それらは問題のリストから削除されます。

As shown in Figure 22 and 23 we deleted User object having firstName == ‘ali new User’

Figure 22

Figure 23

As shown in Figure 24 we empty Realm database using deleteAll() method in realmオブジェクト。 図に示すように realm.isEmptyはtrueを返します

図24

swiftクラスで慣れているように、realmオブジェクト間に何らかの階層を構築する必要があることがあります。 残念ながら、Realmは現在、そのままの状態ではオブジェクト継承をサポートしていません。 回避策: https://forum.realm.io/t/inheritance-with-realm-confusion/153

Useful Links

https://www.raywenderlich.com/9220-realm-tutorial-getting-started
https://www.appcoda.com/realm-database-swift/

https://realm.io/docs/swift/latest/#to-many-relationships
https://realm.io/docs/swift/latest/#optional-properties

https://academy.realm.io/posts/nspredicate-cheatsheet/

https://academy.realm.io/posts/nspredicate-cheatsheet/

コメントを残す

メールアドレスが公開されることはありません。