簡體   English   中英

子類化 swift 通用可解碼類型

[英]Subclassing swift generic decodable type

編輯:正如Rob Napier 所寫,問題存在於 Xcode 9.2 中。 在 Xcode 9.3 中,該問題不再相關。

我的服務器 json 響應都打包在data對象中:

{ 
    "data": {...}
}

所以我有以下通用類型來解析 JSON:

class DataContainer<T: Decodable>: Decodable {

    let data: T

    init(data: T)
        self.data = data
    }
}

大多數情況下它工作正常,但有一個響應,我還需要解析included字段,因此我創建了SpecificDataContainer子類:

class SpecificDataContainer: DataContainer<DataObject> {
    let included: [IncludedObject]

    init() {
        included = []
        super.init(data: DataObject(id: ""))
    }
}

上面的實現給了我編譯器錯誤'required' initializer 'init(from:)' must be provided by subclass of 'DataContainer'

我在SpecificDataContainer實現了init(from:)但編譯器仍然給我同樣的錯誤。

似乎我在這里錯過了一些明顯的東西。 我做錯了什么? 這是我的完整代碼:

import Foundation

let jsonData = """
{
    "data": {
        "id": "some_id"
    },
    "included": [
        {
            "id": "some_id2"
        }
    ]
}
""".data(using:.utf8)!

struct DataObject: Decodable {
    let id: String
}

struct IncludedObject: Decodable {
    let id: String
}

class DataContainer<T: Decodable>: Decodable {
    let data: T

    init(data: T) {
        self.data = data
    }
}

class SpecificDataContainer: DataContainer<DataObject> {
    let included: [IncludedObject]

    init() {
        included = []
        super.init(data: DataObject(id: ""))
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        var includedArray = try container.nestedUnkeyedContainer(forKey: .included)

        var includedObjects:[IncludedObject] = []
        while !includedArray.isAtEnd {
            let includedObject = try includedArray.decode(IncludedObject.self)
            includedObjects.append(includedObject)
        }
        self.included = includedObjects

        try super.init(from: decoder)
    }

    private enum CodingKeys: String, CodingKey {
        case data = "data"
        case included = "included"
    }
}

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
if let obj = try? decoder.decode(SpecificDataContainer.self, from: jsonData) {
    print("object id \(obj.data.id)")
} else {
    print("Fail!")
}

出於某種原因,Xcode 無法識別Codable子類中自動生成的init(from:) (正如 Rob 所說,這可能是一個錯誤)。 在 Xcode 9.3 發布之前,您還可以通過將初始化程序添加到基類來解決此問題:

class DataContainer<T: Decodable>: Decodable {    
    let data: T

    enum CodingKeys: String, CodingKey {
        case data
    }
    
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        data = try container.decode(T.self, forKey: .data)
    }

這似乎是 Xcode 9.2 中的一個錯誤。 在 9.3b4 中,您的代碼很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM