Realm 2.1.0 Swift3.0 アプリのマイグレーション対応

こんにちは。IOS フリーランスエンジニアの永田大祐と申します。:robot:
最近は、IOT人工知能認識系とIOSと繋げれる技術の知見を勉強しています。

今回はRealmの[Realm公式サイト2.1.0](https://realm.io/docs/swift/latest/#migrations)より
マイグレーションの対応を確認したところ、対応がとても簡単でしたので情報共有させていただきます。

#マイグレーションとは
移行、移転、移住、移動、乗換などの意味を持つ英単語です。

IOSでは主に、アプリのバージョンアップに伴い、ユーザーがアプリ内で保存している情報を保持したまま、バージョンアップする対応のことです。（ダウングレードもある思いますが、今回はバージョンアップです。）


#サンプルコードの説明
サンプルコードはこちらです。
https://github.com/daisukenagata/RealmSample

AppDelegate.swiftのdidFinishLaunchingWithOptionsメソッド内でマイグレーション対応のコードを記入しています。
             

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
		
	  let config = Realm.Configuration(
		  // 新しいスキーマバージョンを設定します。 これは以前に使用されたものよりも大きくなければなりません
		  // version（以前にスキーマバージョンを設定していない場合、バージョンは0です）。
		  schemaVersion: 2,
			
		  //スキーマのバージョンが上記のものよりも低い/を開くときに自動的に呼び出されるブロックを設定する
			 migrationBlock: { migration, oldSchemaVersion in
    //まだ何も移行していないので、oldSchemaVersion == 0
    if (oldSchemaVersion < 1) {
		// Realmは新しいプロパティと削除されたプロパティを自動的に検出します
		//そして自動的にディスク上のスキーマを更新する
    }})
		
		// Tell Realm to use this new configuration object for the default Realm
		Realm.Configuration.defaultConfiguration = config
		
		//デフォルトのレルムに対してこの新しい設定オブジェクトを使用するようにRealmに指示します
		let realm = try! Realm()
		print(realm, "Realm")
		print(config,"Realm Version")
		return true
	}



実施理由は、アプリが一番初めに呼ばれるメソッドだからです。その中のschemaVersionを２と設定しています。コンソールで出力結果を確認できます。
realmDataSetクラスにプロパティを追加して、schemaVersionを３と上げると、データベースの内容は保持されたまま、新たなプロパティも追加できます。

###今回の情報はアップデートする内容です。
開発途中のアプリにおいて、データを消去しても構わない場合は、一度アプリをアンインストールするとschemaVersionは0にリセットされます。（データも消去されます。）


#マイグレーションで実施すること
データベースのプロパティ名を変更したり、追加したり、削除したりすることを主に実施します。

サンプルコードのデータベースプロパティはこちらです。

     class realmDataSet: Object {
	
	dynamic var now = NSDate()
	dynamic var ID = String()
	dynamic var Message = String()

    }


通常マイグレーション対応をしないで、プロパティを増やすとサンプルのアプリはクラッシュします。
データベースを使用していれば共通で起きる事象です。

      
     class realmDataSet: Object {
	
	dynamic var now = NSDate()
	dynamic var ID = String()
	dynamic var Message = String()
	dynamic var Message2 = String()

    }

schemaVersion２とした場合にサンプルアプリではAppDelegate.swift内の


    Realm.Configuration.defaultConfiguration = config
    print(config)
print(config)でコンソールに出力結果を出しています。

出力結果

                
コンソール出力を確認すると、schemaVersionが2と出力されていることが確認できます。

その他、詳細の作業は[Realm公式サイト2.1.0](https://realm.io/docs/swift/latest/#migrations)に例題がありますので、参照願います。

#Realmにデータを保持したまま、バージョンアップの検証

###バージョンアップ前 schemaVersionは１
####コンソール出力結果
    
    RealmSwift.Realm Realm
    Realm.Configuration {
	fileURL = file:///var/mobile/Containers/Data/Application/5067B010-C035-4502-B6FF-9364E6D1BF0B/Documents/default.realm;
	inMemoryIdentifier = (null);
	encryptionKey = (null);
	readOnly = 0;
	schemaVersion = 1;
	migrationBlock = <__NSMallocBlock__: 0x17004f0c0>;
	deleteRealmIfMigrationNeeded = 0;
	dynamic = 0;
	customSchema = (null);} Realm Version


####データベースに値を保存した画像
<img width="414" alt="Screen Shot 2016-11-19 at 18.59.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/131469/63d8d621-83d5-9804-c98a-f4f99410d085.png">


###バージョンアップ後 schemaVersionは2(プロパティを増やしたり、変更も可能)
先ほど入力したデータを保持できていました。
####コンソール出力結果
               
    Realm.Configuration {
	fileURL = file:///var/mobile/Containers/Data/Application/12CFBEB8-E651-495B-AE43-4EB0067EEB05/Documents/default.realm;
	inMemoryIdentifier = (null);
	encryptionKey = (null);
	readOnly = 0;
	schemaVersion = 2;
	migrationBlock = <__NSMallocBlock__: 0x174053890>;
	deleteRealmIfMigrationNeeded = 0;
	dynamic = 0;
	customSchema = (null);} Realm Version


####schemaVersion2と設定、データベースのプロパティを増やして出力した画像
（マイグレーションの対応をしないと、データベースを使用するアプリはプロパティを増やして出力するとクラッシュします。）
<img width="414" alt="Screen Shot 2016-11-19 at 19.01.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/131469/e23c943c-93c0-e860-885a-0663c9a01c8d.png">


#まとめ

Realmデータベースを使用したデータを保持したままバージョンアップする方法を記載しました。
Realmのマイグレーション対応は、非常にシンプルで簡単な作業と思います。効率が上がると思います。

次回は、Realm mobile Pratformを実施したアプリケーションの作成、Realm mobile Pratformを共有したいと思います。

貴重な時間を割き、お読み下さいましてありがとうございました。😀