SDD(Sleep-Driven Development)

睡眠の重要性!!睡眠の重要性!!

Realm Xamarin メモ[Xamarin.Forms]

RealmのXamarin版が5/10に出ました。今回はそれを弄ってみたのでメモ等をつらつらと書いていきます。

Realmとは

詳しいことは

realm.io

を見てみてください。

シンプル!!早い!!クロスプラットフォーム!!先進的!!など魅力的な言葉が踊っています。これはぜひ試すしかないでしょう。

なおUWP(とMac)は今のところ非対応ですが将来的に対応したいとのことなので近いうちにサポートされるでしょう(願望)。(realm-dotnetのIssueには既にUWPサポートの声がたくさん)

Realm Browser

Realmのデータベースのデータがどうなってるか知りたいとき、MacユーザにはRealm Browserという便利なものが用意されています。
Realm Browser
ScreenShotの言語は英語なのに入力が日本語なのめっちゃ気になる
使い方は簡単でRealmファイルをダブルクリックして出てきたウインドウのAllowボタンを押すだけです。データが可視化されてしかも編集もできるので大変便利です。
(iOS SimulatorでRealmファイルの場所がわからない場合は

swift - Realm Browserの使い方 - スタック・オーバーフロー

をみれば大丈夫かも)

ただ、上のリンクのバージョンだと一度開くとRealm Xamarinで開けなくなります。(2016/5/17現在) なのでRealm Xamarinで使いたい人はGithubから直接ダウンロードしてきましょう。

インストール

さっそく使っていきましょう。 準備はとても簡単でVSの場合ソリューションを右クリック->Manage Nuget Packages for Solution...でRealmを検索してプロジェクト全てにチェックをした状態でインストールするだけ。とても簡単です。(Versionは0.74.1)

さあ、早速iOSでビルドしてみると・・・

f:id:crocus7724:20160516122302p:plain

失敗しましたorz

原因

どうやらRealmはiOS7以上が必要な模様。VSのXamarin PCLで作るとiOSのデフォルトターゲットは6なので7以上に上げる必要があるみたいです。 なのでiOSの場合はiOSのプロジェクトを右クリック->Properties->iOS ApplicationのDeployment Targetを適宜変更しましょう。

f:id:crocus7724:20160516123401p:plain

Androidも変える必要があるかもしれませんが残念ながらAndroidエミュレータは永眠中なので確かめられません。

もう一度ビルドしてみると成功しました!

使ってみる

それでは早速使っていきましょう。 Realmを使うのに各プロジェクトにそれぞれPath等を書く必要はありません。デフォルトでは'Environment.SpecialFolder.Personalに作られるみたいです(ファイル名はdefault.realm)。名前を変更したい場合はRealm.GetInstance(optionalPath)`のoptionalPathに好きな名前を入れましょう。

今回はお試しなので適当にテーブル作ってデータ突っ込んで取得して画面に表示させます。

public App()
{
            //Realmインスタンス取得
            var realm = Realm.GetInstance();

            //書き込み開始
            using (var transaction = realm.BeginWrite())
            {
                var sample = realm.CreateObject<Human>();
                sample.Age = 18;
                sample.Name = "Hoge hoge";
                
                transaction.Commit();
            }
            
            //テーブルの一番最初のデータ取得
            var human = realm.All<Human>().ToList().FirstOrDefault();

            var content = new ContentPage
            {
                Title = "RealmSample",
                Content = new StackLayout
                {
                    VerticalOptions = LayoutOptions.Center,
                    Children = {
                        new Label {
                            HorizontalTextAlignment = TextAlignment.Center,
                            Text = $"名前:{human.Name}\n年齢:{human.Age}才",
                        }
                    }
                }
            };

            MainPage = new NavigationPage(content);
}

public class Human : RealmObject
{
            public int Age { get; set; }
            public string Name { get; set; }
}

実行してみると・・・

f:id:crocus7724:20160516210907p:plain

無事に追加されています。やったね!

realm.All<Human>()で直接FirstOrDefault()しない理由はまだサポートされてないのでToListを挟まないと使えないからです。ただ、PullRequestも飛んでたし次のバージョンくらいにはサポートされるんじゃないかなーと期待してます。 なお現時点でもFirstメソッドは使えます。

注意点

実際に使ってみてハマったところや気になったところ

使えるデータ

Realmがサポートしているのは

  • bool
  • char
  • byte
  • short
  • int
  • long
  • float
  • double
  • string
  • DateTimeOffset

です。プリミティブ型はNullableもサポートしています。また、RealmObjectとRealmListも設定可能です。

Linqサポート

上にも書きましたが、まだLinqの全てのメソッドをサポートしたわけでは無いみたいです。私が知っているのはFirstOrDefaultとSingleOrDefault、Take、Where系の中でRealmObjectのプロパティ同士の比較(.Where(x=>x.Name==otherX.Name))とか。.Where(x=>x.Name=="Hoge")は大丈夫)です。(他にもありそう)

Transaction外でプロパティセット

上の例でもそうですが、using(var tansaction=realm.BeginWrite())の外でRealmオブジェクトを通して取得したRealmObjectオブジェクトのプロパティのセッターを呼ぶと死にます。 なのでMVVMパターンでうっかりViewModelのプロパティにRealmObjectを紐付けて双方向バインディングで更新をしようとしたら例外で即死します。

ObjectId

特筆すべきことではないっぽいのですが、主キーを設定したいときはObjectId属性をつけるとそうなります。 個人的にそういうのはPrimaryKeyって感じなので最初戸惑ったのですが他でもそう呼ばれているらしい?