2017-10-18 75 views
4

當符合可編碼協議,我不能輕易跳過非可編碼類的可選屬性忽略可編碼對象非可編碼可選屬性

Ride結構我們要跳過編碼解碼driver屬性的和剛剛離開它nil解碼

struct Ride: Codable { 

    public var number: String 
    public var passenger: Passenger? // Codable conforming 
    public var driver: Driver?  // NSObject subclass, doesn't conform to Codable 

    enum CodingKeys: String, CodingKey { 
     case number 
     case passenger 
    } 
    } 

時,在這種情況下,我得到一個編譯錯誤

型「驅動程序」不符合協議「可解」

到目前爲止,我想出了唯一的解決辦法,是通過提供以下方法進行編碼和解碼手動:

public init(from decoder: Decoder) throws { 
    let values = try decoder.container(keyedBy: CodingKeys.self) 
    number = try? values.decode(String.self, forKey: .number) 
    passenger = try? values.decode(Passenger.self, forKey: .passenger) 
} 

public func encode(to encoder: Encoder) throws { 
    var container = encoder.container(keyedBy: CodingKeys.self) 
    try container.encode(number, forKey: .number) 
    try container.encode(passenger, forKey: .passenger) 
} 

有另一種跳過可選屬性的方法?更大的模型會更容易。

+0

這是一個錯誤,請參閱此評論鏈:https://stackoverflow.com/questions/46104870/swift-4-decodable-additional-variables/46105080#comment79173417_46105080 – Hamish

回答

8

嘗試爲driver提供默認值。例如,該編上沒有錯誤的Xcode 9.0

struct Ride: Codable { 
    public var number: String 
    public var passenger: Passenger? 
    public var driver: Driver? = nil 

    private enum CodingKeys: String, CodingKey { 
     case number 
     case passenger 
    } 
} 

struct Passenger: Codable { /* ... */ } 

class Driver: NSObject { /* ... */ } 

快速測試:

let rideJSON = 
""" 
{ 
    "number": "123" 
} 
""".data(using: .utf8)! 

let ride = try! JSONDecoder().decode(Ride.self, from: rideJSON) 
print(ride) /* Ride(number: "123", passenger: nil, driver: nil) */ 

順便說一句,我用了一個private CodingKeys,因爲這是編譯器的默認操作爲什麼好;)

+1

打印的編譯器錯誤在這個問題上非常有用:'注意:不能自動合成'可解碼',因爲'驅動程序'沒有匹配的CodingKey並且沒有默認值' – mklbtz

+0

@mklbtz好的!可能是** Xcode 9.2 ** ... *或*我們第一次完全錯過了這個(有用!)的消息;)很多人甚至不費心閱讀/解釋這些消息...... –