sprite-kit - 在 SpriteKit 中的自定义类上使用 Codable 协议
问题描述
我正在使用 SpriteKit 构建一个应用程序,我想利用 Codable 协议将一个复杂的自定义类保存到 NSUserDefaults。当我这样做时,我收到以下错误:
Cannot automatically synthesize 'Decodable' because 'SKSpriteNode' does not conform to 'Decodable'
该类如下所示(至少具有属性的部分):
class TileNode: SKNode, Codable {
// MARK: - Class Variables
var height = 32
var width = 32
var index = 0
var row = 0
var column = 0
var tileType = ""
// These cannot be global because each tile needs its own instance of them.
var dark = SKSpriteNode()
var light = SKSpriteNode()
// MARK: - Init
override init() {
super.init()
}
init(index:Int, tex: String) {
super.init()
if tileCheck {
print("TileNode: init: creating tile with texture: \(tex).")
}
self.isUserInteractionEnabled = false
self.index = index
self.zPosition = 10
self.name = "Tile \(index)"
self.tileType = tex
}
}
所以,我的问题是,当您需要将 SKSpriteNode 之类的东西作为类变量时,如何在自定义对象上使用可编码协议?
解决方案
很明显,这个问题是因为SKSpriteNode
不符合Codable
协议。因此,以下步骤使自定义类 LikeSKSpriteNode
能够使用Codable
协议很好地工作。
- 声明自定义编码键以定义要编码或解码的属性列表
- 实现
required init(from:)
方法转换Data
成SKSpriteNode
- 实现
encode(to:)
方法转换SKSpriteNode
成Data
这是示例:
class TileNode: SKNode, Codable {
var height = 32.0
var width = 32.0
var index = 0
var row = 0
var column = 0
var tileType = ""
// These cannot be global because each tile needs its own instance of them.
var dark = SKSpriteNode()
var light = SKSpriteNode()
enum CodingKeys: String, CodingKey {
case height
case width
case index
case row
case column
case tileType
case dark
case light
}
init(index:Int, tex: String) {
super.init()
if tileCheck {
print("TileNode: init: creating tile with texture: \(tex).")
}
self.isUserInteractionEnabled = false
self.index = index
self.zPosition = 10
self.name = "Tile \(index)"
self.tileType = tex
}
required init(from decoder: Decoder) throws {
super.init()
let values = try decoder.container(keyedBy: CodingKeys.self)
height = try values.decode(Double.self, forKey: .height)
width = try values.decode(Double.self, forKey: .width)
index = try values.decode(Int.self, forKey: .index)
row = try values.decode(Int.self, forKey: .row)
column = try values.decode(Int.self, forKey: .column)
tileType = try values.decode(String.self, forKey: .tileType)
let darkData = try values.decode(Data.self, forKey: .dark)
dark = NSKeyedUnarchiver.unarchiveObject(with: darkData) as? SKSpriteNode ?? SKSpriteNode()
let lightData = try values.decode(Data.self, forKey: .light)
light = NSKeyedUnarchiver.unarchiveObject(with: lightData) as? SKSpriteNode ?? SKSpriteNode()
}
required init?(coder aDecoder: NSCoder) {
// subclass of SKNode must implement this method
fatalError("init(coder:) has not been implemented")
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(height, forKey: .height)
try container.encode(width, forKey: .width)
try container.encode(index, forKey: .index)
try container.encode(row, forKey: .row)
try container.encode(column, forKey: .column)
try container.encode(tileType, forKey: .tileType)
let darkData = NSKeyedArchiver.archivedData(withRootObject: dark)
try container.encode(darkData, forKey: .dark)
let lightData = NSKeyedArchiver.archivedData(withRootObject: light)
try container.encode(lightData, forKey: .light)
}
}
用法
编码数据并将数据保存在 UserDefaults 中:
let node = TileNode(index: 3, tex: "Text")
node.height = 33.0
let dark = SKSpriteNode()
dark.anchorPoint = CGPoint(x: 12.3, y: 45.6)
dark.color = UIColor.red
node.dark = dark
let encoder = JSONEncoder()
do {
let encoded = try encoder.encode(node)
UserDefaults.standard.set(encoded, forKey: "Node")
} catch {
print(error.localizedDescription)
}
从 UserDefaults 中检索数据并解码数据:
let docoder = JSONDecoder()
do {
let nodeData = UserDefaults.standard.object(forKey: "Node") as! Data
let node = try docoder.decode(TileNode.self, from: nodeData)
} catch {
print(error.localizedDescription)
}
推荐阅读
- python - 如何将字符从希腊语转换为英语 python
- go - 从 net.Conn 读取时出现随机 io.EOF 错误
- encryption - 如何将新的 CA.pem 文件重新加载或更新到现有的 SSL CTX 中,以避免 X509_STORE_add_cert:cert 已经在哈希表异常中
- bootstrap-4 - Bootstrap 4 未在 Chrome 中正确显示类
- sql - Alembic - 创建顺序迁移
- python - >>> print 出现语法错误(x“大于”y)
- android-activity - 在所有活动问题中显示导航抽屉
- python - 无法在 Windows 中安装 pycurl
- r - ggplot2:仅斜体某些 x 轴列
- c++ - 为什么Boost multi_index 只修改第一个索引的键时,对第二个索引进行比较?