9152


RealmとObjectMapper(<https://github.com/Hearst-
DD/ObjectMapper>)を組み合わせで以下のようなモデルを作っているのですが、このモデルを User(forPrimaryKey: "1")
の呼び出し方でインスタンス化しようとした場合、 **Cannot invoke initializer for type 'User' with an
argument list of type '(forPrimaryKey: String)'** と怒られてしまいます。

[code]

    class User: RLMObject, Mappable {
    
        var id:String?
        var name:String?
    
        required init?(_ map: Map) {
            super.init()
            mapping(map)
        }
    
        func mapping(map: Map) {
            id <- map["id"]
            name <- map["name"]
        }
    
        override class func primaryKey() -> String {
            return "id"
        }
    }
    
[/code]

おそらく、RLMObjectクラスとMappableプロトコルの多重継承が原因だとおもうのですが、なぜMappableプロトコルを継承すると、User(forPrimaryKey:
"1") が利用できなくなるのが理解できておりません。  
RealmというよりはSwiftの言語利用の話になると思うのですが、ご存知の方、お手数ですがご教授いただけると助かります。

Mappableプロトコルの内容は以下です。

[code]

    public protocol Mappable {
        init?(_ map: Map)
        mutating func mapping(map: Map)
    }
    
[/code]

再現コードを以下に置きます。  
<https://github.com/okitsutakatomo/RealmWithObjectMapper>


CC BY-SA 3.0
2015-04-14T03:29:29.537
9137
2015-04-15T08:57:19.707
9309
question
swift realm
RealmとObjectMapperの組み合わせで Cannot invoke initializer for type 'User' with an argument list of type '(forPrimaryKey: String)


`Mappable`プロトコルのイニシャライザが`RLMObject`で定義されている`objectForPrimaryKey:`からSwiftにマッピングされたイニシャライザを隠してしまうようなので、少し無理やりですが、下記のようにエクステンションで別名のメソッドを定義して呼び出すのはいかがでしょうか？

[code]

    extension RLMObject {
    
        class func objectInRealm(realm: RLMRealm, forIdentifier: AnyObject) -> RLMObject? {
            return self(inRealm: realm, forPrimaryKey: forIdentifier);
        }
    
        class func objectForIdentifier(identifier: AnyObject) -> RLMObject? {
            return self(forPrimaryKey: identifier)
        }
    }
    
[/code]

また、試す過程で`ObjectMapper`がJSONからオブジェクトを生成するときに呼び出す`init`で正しく`RLMObject`クラスの`init`が呼ばれなかったのを確認しました。  
そのため、おそらく下記のように`init`をオーバーライドする必要があります。

また、Realmで使用するモデルのクラス（`RLMObject`のサブクラス）のプロパティはすべて`dynamic`修飾子を付加する必要があります。そうしないと、値を正しく取り出すことができません。

また、プライマリキーの型がオプショナルだと、`ObjectMapper`がJSONからオブジェクトを生成する際にプライマリキーが`nil`という例外で失敗したので、定義を直して初期値を与えるようにしました。

[code]

    class User: RLMObject, Mappable {
        dynamic var id: String = ""
        dynamic var username: String = ""
    
        // For Realm
        override init!() {
            super.init()
        }
    
        override init!(objectSchema schema: RLMObjectSchema!) {
            super.init(objectSchema: schema)
        }
    
        override class func primaryKey() -> String {
            return "id"
        }
    
        // For ObjectMapper
        required convenience init?(_ map: Map) {
            self.init()
            mapping(map)
        }
    
        func mapping(map: Map) {
            id          <- map["id"]
            username    <- map["username"]
        }
    }
    
[/code]

上記の修正したコードについては、次のコードで動作を確認しました。

[code]

    let json = "{\"id\": \"1\", \"name\": \"katsumi\"}"
    let user = Mapper<User>().map(json)
    
    println("user: \(user?.id, user?.name)")
    
    let realm = RLMRealm.defaultRealm()
    
    realm.transactionWithBlock { () -> Void in
        realm.addOrUpdateObject(user)
    }
    
    let results = User.objectsInRealm(realm, "id = %@", "1")
    println("results: \(results)")
    
    if let u = User.objectForIdentifier("1") as? User {
        println("user: \(u)")
    } else {
        println("user: null")
    }
    
[/code]


CC BY-SA 3.0
2015-04-14T08:32:04.853
9152
2015-04-14T17:44:51.427
2015-04-14T17:44:51.427
5519
5519
9137
answer


Realmの公式な見解としましては、[ObjectMapper](https://github.com/Hearst-DD/ObjectMapper
"ObjectMapper")は使えないことはないけれど、RealmオブジェクトをJSON文字列に戻す`toJON`メソッドが失敗するなど、非互換なところも多いので、現状は他のマッピングライブラリを検討するのが現実的ではないかと考えています。

例えば、下記の[Realm-JSON](https://github.com/matthewcheok/Realm-JSON "Realm-
JSON")はMantleに似たAPIを持つライブラリで、たいていのアプリケーションによく合って使いやすいと思います。

<https://github.com/matthewcheok/Realm-JSON>

また、将来的にはRealm公式のJSON<=>RLMObjectのマッピングライブラリ（もしくは機能）を提供する予定があります。


CC BY-SA 3.0
2015-04-15T08:44:11.730
9197
2015-04-15T08:57:19.707
2015-04-15T08:57:19.707
5519
5519
9137
answer