【发布时间】:2018-01-11 02:16:56
【问题描述】:
我有一个 SKSpriteNode 对象数组,我想将它们持久化到 UserDefaults。在下面的代码 (or see demo project on GitHub) 中,我使用 NSKeyedUnarchiver 将数组编码为数据,然后再将其设置为默认值。但是当我取消归档数据时,对象的engineSize 属性被重置为默认值 0。
Car.swift
import SpriteKit
class Car: SKSpriteNode {
var engineSize: Int = 0
init() {
super.init(texture: nil, color: .blue, size: CGSize(width: 100, height: 100))
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
GameScene.swift
import SpriteKit
class GameScene: SKScene {
let defaults = UserDefaults.standard
var carArray = [Car]()
override func didMove(to view: SKView) {
for _ in 1...3 {
let car = Car()
car.engineSize = 2000
carArray.append(car)
}
// Save to defaults
defaults.set(NSKeyedArchiver.archivedData(withRootObject: carArray), forKey: "carArrayKey")
// Restore from defaults
let arrayData = defaults.data(forKey: "carArrayKey")
carArray = NSKeyedUnarchiver.unarchiveObject(with: arrayData!) as! [Car]
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for c in carArray {
print("Car's engine size is \(c.engineSize)")
}
}
}
This answer 引导我尝试在 Car 类上实现编码器/解码器方法:
Car.swift(更新)
import SpriteKit
class Car: SKSpriteNode {
var engineSize: Int = 0
init() {
super.init(texture: nil, color: .blue, size: CGSize(width: 100, height: 100))
}
required convenience public init(coder decoder: NSCoder) {
self.init()
if let engineSize = decoder.decodeObject(forKey: "engineSize") as? Int {
self.engineSize = engineSize
}
}
func encodeWithCoder(coder : NSCoder) {
coder.encode(self.engineSize, forKey: "engineSize")
}
}
但是,这似乎不起作用。 GameScene 仍在将 engineSize 打印为 0。我执行编码器/解码器是否错误?当engineSize 属性从默认值恢复时,我可以做些什么来防止它们重置为 0?
更新
这是我更新后的 Car 课程,因为我正试图让它与 rmaddy 的建议一起使用:
import SpriteKit
class Car: SKSpriteNode {
var engineSize: Int = 0
init() {
super.init(texture: nil, color: .blue, size: CGSize(width: 100, height: 100))
}
required init?(coder decoder: NSCoder) {
super.init(coder: decoder)
if let engineSize = decoder.decodeObject(forKey: "engineSize") as? Int {
self.engineSize = engineSize
}
}
func encodeWithCoder(coder : NSCoder) {
super.encode(with: coder)
coder.encode(self.engineSize, forKey: "engineSize")
}
}
代码编译并运行,但engineSize 属性在保存为默认值时仍被重置为 0。
【问题讨论】:
-
您需要在
Car的init(coder:)和encodeWithCoder(coder:)方法中调用super。 -
您还应该删除并重新安装您的应用程序,以确保之前尝试的 UserDefaults 中没有错误数据。
-
我添加了
super.encode(with: coder)好的,但是在init(coder:)中,编译器不喜欢调用super.init(decoder)。它抱怨:Convenience initializer for 'Car' must delegate (with 'self.init') rather than chaining to a superclass initializer (with 'super.init') -
init(coder:)不应标记为便利初始化程序。 -
@rmaddy 删除
convenience会产生错误。我更新了帖子以显示我正在尝试的代码。
标签: ios swift sprite-kit nskeyedarchiver userdefaults