簡體   English   中英

在Argo中解碼泛型類型

[英]Decoding a generic type in Argo

我正在使用Thoughtbot的Argo框架將JSON對象解析為模型。

我遇到了一個問題,我有一個協議及其擴展,如此

protocol SomeProtocol {
    associatedtype Model
    func foo()     
}

extension SomeProtocol where Model: Decodable {
    func foo() -> Model? {
        // someJSON is AnyObject in this case, say, from a network call
        guard let model: Model = decode(someJSON) else { return nil }
        return model
    }
}

並且符合此協議的類看起來像這樣

class SomeClass: SomeProtocol {
    typealias Model = ArgoModel

    func bar() {
        print(foo())
    }
}

和這樣的模型

struct ArgoModel {
    let id: String
}

extension ArgoModel: Decodable {
    static func decode(j: AnyObject) -> Decoded<ArgoModel> {
        return curry(self.init)
            <^> j <| "id"
    }
}

(我也在使用他們的Curry庫來討論init方法)

我遇到的問題是,在SomeProtocol擴展中,關聯類型Model不能被Argo解碼。 我得到的錯誤是

No 'decode' candidates produced the expected contextual result type 'Self.Model?'

這是Swift類型系統的限制嗎? 還是有什么我想念的?

在研究了一些之后,似乎這是Swift類型系統的限制,如Swift 2.3。 問題的確切原因是諸如集合和monad之類的上下文類型不能符合Argo中的Decodable。 所以我的模型只要不包含在集合中就可以工作。 使用Swift 3.0,目標是允許

使受約束的擴展符合新協議的能力(即,Equatable元素的數組是Equatable)

如本期所述: https//github.com/thoughtbot/Argo/issues/334

我目前的解決方法是使其中包含的車型陣列復數模型,並進行解碼在SomeProtocol擴展。 所以現在我的模型看起來像這樣:

struct ArgoModels {
    let models: [ArgoModel]
}

extension ArgoModels: Decodable {
    static func decode(j: JSON) -> Decoded<ArgoModels> {
        switch j {
            case .Array(let a):
                return curry(self.init) <^> sequence(a.map(ArgoModel.decode))
            default:
                return .typeMismatch("Array", actual: j)
        }
    }
}

struct ArgoModel {
    let id: String
}

extension ArgoModel: Decodable {
    static func decode(j: AnyObject) -> Decoded<ArgoModel> {
        return curry(self.init)
            <^> j <| "id"
    }
}

然后在實現類中,我可以創建一個typealias,Model可以是一個對象,也可以是通用方式的集合。

暫無
暫無

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

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