酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Xamarin.FormsでRealm Xamarinを使ってみた

Xamarin.FormsでRealm Xamarinを使ってみました。

プロジェクトを作成する

適当にプロジェクトを作成します。

f:id:ch3cooh393:20170108224028p:plain

f:id:ch3cooh393:20170108224035p:plain

f:id:ch3cooh393:20170108224043p:plain

UIを整える

ボタンをタップされたら、押されたタイミングの時刻(時分秒)をRealmに登録して、さらにListViewに表示させたいと思います。

RealmSamplePage.xaml

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:local="clr-namespace:RealmSample" 
    x:Class="RealmSample.RealmSamplePage">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
            iOS="0,20,0,0" />
    </ContentPage.Padding>
    
    <StackLayout Orientation="Vertical">
        <StackLayout Orientation="Horizontal">
            <Label Text="Welcome to Xamarin Forms!" />
            <Button Text="Add" Clicked="AddAction" />
        </StackLayout>
        <ContentView HeightRequest="1" BackgroundColor="Black" />

        <ListView x:Name="listView" />
        
    </StackLayout>
</ContentPage>

RealmSamplePage.xaml.cs

ボタンが押されたらAddActionが呼ばれます。

using Xamarin.Forms;

namespace RealmSample
{
    public partial class RealmSamplePage : ContentPage
    {
        public RealmSamplePage()
        {
            InitializeComponent();
        }

        void AddAction(object sender, System.EventArgs e)
        {
//         throw new NotImplementedException();
        }
    }
}

実行してみました。適当にこんな感じにしました。

f:id:ch3cooh393:20170108223850p:plain

Realm Xamarinをインストールする

Realmをインストールします。iOSのプロジェクトではPodfileに書いて、Androidのプロジェクトではgradleに追記してインストールしました。

XamarinではNugetを使ってインストールします。

f:id:ch3cooh393:20170108231912p:plain

f:id:ch3cooh393:20170108231917p:plain

[Add Package]ボタンをクリックしてインストールします。

PCL側だけではなく、RealmSample.DroidとRealmSample.iOSのプラットフォームにもパッケージを追加しておきます。

Itemクラスを作る

Realmのデータベースに格納するオブジェクトのクラスを作成します。

なんでも良いのですがここではItemクラスを作成しました。TimeStringにボタンをクリックした時刻を格納しようと思います。

using System;
using Realms;

namespace RealmSample
{
    public class Item : RealmObject
    {
        public string TimeString { get; set; }
    }
}

RealmSamplePage.xaml.cs

ボタンが押されるとAddActionメソッドが実行されます。このメソッドの中でRealmへの追加とListViewのデータソースの追加を行いました。

using Xamarin.Forms;
using Realms;
using System.Collections.ObjectModel;
using System;
using System.Linq;

namespace RealmSample
{
    public partial class RealmSamplePage : ContentPage
    {
        ObservableCollection<string> items = new ObservableCollection<string>();

        public RealmSamplePage()
        {
            InitializeComponent();

            listView.ItemsSource = items;
        }

        void AddAction(object sender, System.EventArgs e)
        {
            var time = DateTime.UtcNow.ToString("HH:mm:ss");

            // RealmにItemオブジェクトを追加する
            var realm = Realm.GetInstance();
            realm.Write(() =>
            {
                realm.Add(new Item { TimeString = time });
            });

            // ListViewの先頭にも時刻を表示させる
            items.Insert(0, time);
        }
    }
}

一度アプリをkillして、再度立ち上げると今までRealmに追加したはずのデータが表示されていません。PageのコンストラクタでRealmからItemオブジェクトを取り出してListViewに表示されるようにしました。

using Xamarin.Forms;
using Realms;
using System.Collections.ObjectModel;
using System;
using System.Linq;

namespace RealmSample
{
    public partial class RealmSamplePage : ContentPage
    {
        ObservableCollection<string> items = new ObservableCollection<string>();

        public RealmSamplePage()
        {
            InitializeComponent();

            // Realmから登録されたItemオブジェクトを取り出してソートする
            var realm = Realm.GetInstance();
            var allItems = realm.All<Item>().OrderByDescending((arg) => arg.TimeString);

            // データソースに時刻を追加する
            foreach (var i in allItems)
            {
                items.Add(i.TimeString);
            }
            listView.ItemsSource = items;
        }

        void AddAction(object sender, System.EventArgs e)
        {
            // RealmにItemオブジェクトを追加する
            var realm = Realm.GetInstance();
            realm.Write(() =>
            {
                realm.Add(new Item { TimeString = time });
            });

            // ListViewの先頭にも時刻を表示させる
            items.Insert(0, time);
        }
    }
}

f:id:ch3cooh393:20170108231042p:plain

トラブルシューティング

このボタンを押すとItemを追加するだけのサンプルアプリを書いている時にもいくつか問題が発生しました。

実行時に例外が発生してしまう

RealmSamplePageのコンストラクタにvar realm = Realm.GetInstance();の1行を追加すると、実行時に例外が発生してしまいました。

f:id:ch3cooh393:20170108225351p:plain

System.IO.FileNotFoundExceptionがスルーされました
Could not load file or assembly 'Realm, Version=0.81.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.

実行するプラットフォーム(この場合はRealmSample.iOS)のパッケージにもRealmをインストールする必要がありました。

f:id:ch3cooh393:20170108225404p:plain