2017-06-15 39 views
2

实施例:如何在引用类型中使用Codable协议?

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 

输出:

true 
false 

如何使用可编码协议参考类型?

行为在未来可能会改变吗? https://github.com/apple/swift-evolution/blob/master/proposals/0167-swift-encoders.md

+0

我需要引用类型 – rtnm

回答

6

这是JSON的基础,而不是Codable。 JSON是值的编码。它不记录引用;它不是格式的一部分。如果你想跟踪引用,你必须自己将它存储在JSON中,编码为objectIdentifier。然后你需要加入具有相同标识符的东西。但这超出了Codable的范围,因为底层格式没有这个概念。你需要创建一些其他格式(可能使用JSON作为其基础值格式,NSKeyedArchiver使用属性列表作为其基础值格式)。

JSON不是对象图形存储格式;正如我所说这是一个值编码。如果你想要一个对象图,这就是NSKeyedArchiver的用途。如果你想要一个非Cocoa解决方案,你需要实现一个新的EncoderDecoder,它们实现了与归档器相同的基本思想。这不是什么JSONEncoder是。但如果可能的话,我会使用NSKeyedArchiver;它是为此而设计的。

注意,SE-0167说有上NSKeyedArchiverencodeCodable方法应该是让你混用Codable类型的NSCoding类型(并让斯威夫特类型参与NSKeyedArchiver),但我没有看到它在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 未来,NSKeyedArchiver将支持encodeCodable方法。 但我想打开基于文本的存储格式(JSON)。 – rtnm

+0

“你需要实现一个新的编码器和解码器,它实现了与归档器相同的基本思想” - 它是一个变种 – rtnm

+0

今天stdlib中没有这样的东西存在。你必须找到它或建立它。 –

1

看来编码器目前不尊重引用,而是保存一个单独的实例每当它被引用时都是同一个对象,这就是为什么===失败。您可以将其更改为==并为您的课程实施Equatable,该课程应解决此问题或对问题状态的评论使用结构。

+0

我想在解码后得到一个精确的副本。 – rtnm

相关问题