2017-08-02 11 views
3

問題点リストタイプがCodableに準拠していません。以下のクラスはレルムに挿入できません。 Codableでリストタイプを使用するには? (RealmSwift)

class Book: Codable { 
    var name: String = "" 
    var author: String = "" 
    var tags = [String]() 
} 

例えば

は、レルムに格納このクラスは、それがコード可能に適合する代わり [String]

class Book: Object, Codable { 
    @objc dynamic var name: String = "" 
    @objc dynamic var author: String = "" 
    var tags = List<Tag>() 

    required convenience init(from decoder: Decoder) throws { 
     self.init() 
     let container = try decoder.container(keyedBy: CodingKeys.self) 
     name = try container.decode(String.self, forKey: .name) 
     author = try container.decode(String.self, forKey: .author) 
     tags = try container.decode(List<Tag>.self, forKey: .tags) // this is problem. 
    } 
} 

class Tag: Object, Codable { 
    @objc dynamic var string: String = "" 

    required convenience init(from decoder: Decoder) throws { 
     self.init() 
     let container = try decoder.container(keyedBy: CodingKeys.self) 
     string = try container.decode(String.self, forKey: .string) 
    } 
} 

List<Object>タイプを使用する必要がある場合、上記クラスは、コード可能に準拠検討しますそれはDecodableプロトコルを実装する必要があります。 (required convenience init(from decoder: Decoder) throws

しかし、ListタイプはCodableDecodable)に準拠していない、クラスがListタイプを持っている場合はコード可能なを使用することは不可能です。

この問題を解決するにはどうすればよいですか?

ありがとう、

+1

はそれがCodable' 'に準拠するためにリストに拡張子を書く:JSONレスポンス、モデル& URLSessionでより多くの詳細については

。 –

答えて

5

あなたはほぼあります。イニシャライザの内部では、デコードされた配列を使用してリストを初期化できます。基本的には、受け入れ答えで一つだけ問題があります

let tagsArray = try container.decode([Tag].self, forKey: .tags) 
tags = List(tagsArray) // Now you are good 
+0

ありがとう、うまくいきます。 –

+0

@YosukeImairiあなたの質問に答えた場合は、受け入れられた回答としてマークすることができます。 –

2

tags = try container.decode(List<Tag>.self, forKey: .tags) // this is problem. 

を変更。レルムはlet(定数)にする必要があります。ベストプラクティスに従うようにソリューションを変更するには、リストをletにして、結果を配列に追加してループスルーする必要があります。 let tags = List<Tag>()

// Change this Line in [Your Code] 
// to a let (Constant) 

var tags = List<Tag>()次にこれはあなたのレルム/スウィフト4コード可能なモデルを作成する方法です

let tagsArray = try container.decode([Tag].self, forKey: .tags) 
tagsArray.forEach{ tags.append($0) } 
+0

nice answer、1つの質問:ここにリストにタグを追加すると、オブジェクトが何らかの形で再利用されている場合、古いタグが保持される可能性はありますか? –

+0

これは 'init'でしか実行されないので、私はそこにチャンスがあるとは思わない。 'tagsArray'は新しい空の' Array'としてインスタンス化されます。この 'tagsArray'に追加できる別のメソッドがある場合は、既に存在するすべての既存のタグを持ちます。もしそうしたなら、おそらくメソッドタグを削除することもできます。しかし、私は一般的にあなたは安全であるべきだと思います。 –

+0

'tagsArray.forEach ... 'の代わりに' tags.append(objectsIn:tagsArray) 'を使うべきでしょう。 –

0

tags = try container.decode(List<Tag>.self, forKey: .tags) 

を変更。 Read this article

import RealmSwift 

class VendorsList : Object, Decodable { 
    @objc dynamic var id : Int = 0 
    @objc dynamic var name : String? 
    @objc dynamic var logo : String? 
    // Create your Realm List. 
    var kitchensList = List<VendorKitchens>() 

    override class func primaryKey() -> String? { 
     return "id" 
    } 

    private enum CodingKeys: String, CodingKey { 
     case id 
     case name 
     case logo 
     // Set JSON Object Key 
     case kitchensList = "kitchens" 

    } 

    public required convenience init(from decoder: Decoder) throws { 
     self.init() 
     let container = try decoder.container(keyedBy: CodingKeys.self) 
     self.id = try container.decode(Int.self, forKey: .id) 
     self.name = try container.decode(String.self, forKey: .name) 
     self.logo = try container.decode(String.self, forKey: .logo) 
     // Map your JSON Array response 
     let kitchens = try container.decodeIfPresent([VendorKitchens].self, forKey: .kitchensList) ?? [VendorKitchens()] 
     kitchensList.append(objectsIn: kitchens) 

    } 

} 


class VendorKitchens : Object, Decodable { 
    @objc dynamic var id : Int = 0 
    @objc dynamic var name : String? 

    override class func primaryKey() -> String? { 
     return "id" 
    } 

    private enum CodingKeys: String, CodingKey { 
     case id 
     case name 
    } 
} 
+1

これはコード化できません!Codableを使用できる場合は、エラーが発生します。「タイプ 'VendorsList'がプロトコル 'Encodable'に準拠していません。リストはvarではないはずです。 –

関連する問題