LoginSignup
0
0

More than 1 year has passed since last update.

RealmモデルをiPhoneからApple Watchに送信する方法

Posted at

はじめに

RealmモデルをApple Watchに直接送信することはできないようです。
Codable属性を指定して、JSON等にエンコードすることで送信することができます。

エンコード方法については記事1の補足になります。

ただし、Realmのバージョンが変わったことで若干仕様が変わっているようなので、本記事ではRealm ver.10.34.1現在での情報ということでご参考にしていただければと思います。

エンコード方法

まずモデルを定義します。

import Foundation
import RealmSwift

class Album: Object, Codable {
    @Persisted var id: String = UUID().uuidString
    @Persisted var name: String = ""
    @Persisted var content = RealmSwift.List<ImageInfo>()

    override public static func primaryKey() -> String? {
        return "id"
    }
    
    private enum CodingKeys: String, CodingKey {
        case id
        case name
        case content
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(name, forKey: .name)
        try container.encode(content, forKey: .content)

    }
}

また

import Foundation
import RealmSwift

class ImageInfo: Object, Codable {
    @Persisted var id: String = UUID().uuidString
    @Persisted var name: String = ""
    @Persisted var savePath: String = ""

    override public static func primaryKey() -> String? {
        return "id"
    }
    
    private enum CodingKeys: String, CodingKey {
        case id
        case name
        case savePath
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(name, forKey: .name)
        try container.encode(savePath, forKey: .savePath)
    }
}

AlbumモデルのコンテンツとしてImageInfoを持っているモデルを定義してみました。

各モデルにCodable属性が指定されています。両方のモデルに必要なことに注意してください。
そうすることで、こういった入れ子構造のモデルもJSON化可能です。

では、実際にエンコードしていきます。
(今回はrealm.objects()ですべてのオブジェクトを取得し、それぞれについてエンコードしてArrayに追加&Array自体をさらにエンコードする、という形にしました)

// 読み込み&encode処理
let realm = try! Realm()
let albums: List = realm.objects(Album.self)

do{
    var dataArray: [Data] = []
    for album in albums {
            let albumData = try JSONEncoder().encode(album)
            dataArray.append(albumData)
    }
    let dataArrayEncoded = try JSONEncoder().encode(dataArray)
}catch{
    print(error)
}

Watch側でデコードしてRealmに保存するコードは以下です。

// decode&保存処理
do{

    let realm = try Realm()

    let dataArray = try JSONDecoder().decode([Data].self, from: dataArrayEncoded)

    for data in dataArray{
        
        let album = try JSONDecoder().decode(Album.self, from: data)
        
        try realm.write() {
            realm.add(album, update: .modified)  // データが無ければ追加、あったら上書き
        }
        
    }
    
}catch{
    print("decode error")
    print(error)
}

Watch側で保存したDBを覗くと以下のようになります。

let realm = try! Realm()
let albums = realm.objects(Album.self)
print(albums)

[Album {
	id = 6342D5AD-339B-4876-8644-C6704A7A2ABF;
	name = All;
	content = List<ImageInfo> <0x6000020013f0> (
		[0] ImageInfo {
			id = 62C40A75-C52A-4CA4-BEA8-9A3D65FF8A33;
			name = image;
			savePath = file:///xxx.jpg;
		},
		[1] ImageInfo {
			id = 605AECA6-8CAD-4461-B7DD-F88F91EBA0D9;
			name = image;
			savePath = file:///xxx.jpg;
		},
		[2] ImageInfo {
			id = B31D5527-57B2-4F13-B1A8-7DB1A2FB068A;
			name = image;
			savePath = file:///xxx.jpg;
		}
	);
}, Album {
	id = AACD238E-3941-40E5-9DBB-C242532F488C;
	name = New;
	content = List<ImageInfo> <0x600002008c60> (
		[0] ImageInfo {
			id = 605AECA6-8CAD-4461-B7DD-F88F91EBA0D9;
			name = image;
			savePath = file:///xxx.jpg;
		},
		[1] ImageInfo {
			id = B31D5527-57B2-4F13-B1A8-7DB1A2FB068A;
			name = image;
			savePath = file:///xxx.jpg;
		}
	);
}]

エンコード処理を以下のようにしないのか?と思うかもしれません。

let albumData = try Album.encode(to: JSONEncoder())

せっかくAlbumモデルで定義したencodeを使っていないので「あれ?」となるのですが、上の例だと、以下のようなエラーになります。

argument type 'jsonencoder' does not conform to expected type 'encoder'

これにはJSONEncoder()の定義が起因しているようです。2 3

送信方法

JSONエンコードすれば、Data型になるので、Watch ConnectivityのsendMessageData()等で送ることができます。

参考文献

  1. https://qiita.com/cottpan/items/b75abd5d4e4ce73e00f2

  2. https://stackoverflow.com/questions/56366704/argument-type-does-not-conform-to-encodable

  3. https://kaitlin.dev/2019/01/07/jsonencoder-encoder.html

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0