2017-06-15 1 views
2

Beispiel:Wie Codable-Protokoll mit Referenztypen verwenden?

import Foundation 

class Player: Codable { 
    let name: String 
    init(name: String) { 
     self.name = name 
    } 
} 

class Team: Codable { 
    let players: [Player] 
    let capitan: Player 
    init(players: [Player], capitan: Player) { 
     self.players = players 
     self.capitan = capitan 
    } 
} 

let player1 = Player(name: "p1") 
let player2 = Player(name: "p2") 

let team = Team(players: [player1, player2], capitan: player1) 

print(team.players[0] === team.capitan) // true 

let encoder = JSONEncoder() 
let data = try encoder.encode(team) 

let decoder = JSONDecoder() 
let team2 = try decoder.decode(Team.self, from: data) 

print(team2.players[0] === team2.capitan) // false 

Ausgang:

true 
false 

Wie Kodierbare Protokoll mit Referenztypen benutzen?

Das Verhalten kann sich in Zukunft ändern? https://github.com/apple/swift-evolution/blob/master/proposals/0167-swift-encoders.md

+0

Ich brauche Referenztypen – rtnm

Antwort

6

Dies ist grundlegend für JSON, nicht codierbar. JSON ist eine Codierung von Werten. Referenzen werden nicht erfasst; Es ist nicht Teil des Formats. Wenn Sie Verweise verfolgen möchten, müssen Sie diese in JSON selbst speichern, indem Sie objectIdentifier codieren. Sie müssten dann Dinge zusammenführen, die denselben Bezeichner haben. Aber das liegt außerhalb des Geltungsbereichs von Codable, da das zugrundeliegende Format nicht das Konzept hat. Sie müssten ein anderes Format erstellen (vielleicht, dass JSON als zugrunde liegendes Wertformat verwendet wurde, so wie NSKeyedArchiver Eigenschaftslisten als zugrunde liegendes Wertformat verwendet).

JSON ist kein Objektgraphspeicherformat; Wie gesagt, es ist eine Wertcodierung. Wenn Sie ein Objektdiagramm haben möchten, ist das NSKeyedArchiver für. Wenn Sie eine Nicht-Cocoa-Lösung wünschen, müssen Sie eine neue Encoder und Decoder implementieren, die die gleiche Grundidee wie die Archiver implementiert. Das ist nicht, was JSONEncoder ist. Aber ich würde NSKeyedArchiver verwenden, wenn möglich; es ist dafür ausgelegt.

Beachten Sie, dass SE-0167 sagt, dass es eine neue encodeCodable Methode auf NSKeyedArchiver, die angeblich Sie Codable Typen mit NSCoding Typen lassen intermix (und lassen Swift Arten in NSKeyedArchiver teilnehmen), aber ich sehe es nicht in Xcode 9 beta 1.

+0

https://github.com/apple/swift-evolution/blob/master/proposals/0166-swift-archival-serialization.md https://github.com/apple/swift-evolution/blob/master/proposals /0167-swift-encoders.md In Zukunft wird NSKeyedArchiver die Methode encodeCodable unterstützen. Aber ich möchte das textbasierte Speicherformat (JSON) öffnen. – rtnm

+0

"Sie müssten einen neuen Encoder und Decoder implementieren, der die gleiche Grundidee wie die Archiver implementiert" - es ist eine Variante – rtnm

+0

So etwas gibt es heute in stdlib nicht. Du müsstest es finden oder bauen. –

1

Es sieht so aus, als ob der Encoder derzeit Referenzen nicht respektiert und stattdessen eine separate Instanz des Das gleiche Objekt jedes Mal, wenn es referenziert wird, warum === schlägt fehl. Sie können es in == ändern und Equatable für Ihre Klassen implementieren, die dies beheben sollten, oder wie der Kommentar zu den Fragezuständen structs verwendet.

+0

Ich möchte eine genaue Kopie nach der Decodierung erhalten. – rtnm

Verwandte Themen