这就是困境。
我有一个管理精灵套装游戏高分的课程。 “高分”功能有效,但“计算所有分数”。
在游戏中,玩家必须收集浆果。我想跟踪一生的浆果。
这是我的班级来管理高分。
class Score: NSObject, NSCoding {
var score: Int
var highScore: Int
var lifeTimeScore: Int
static let DocumentsDirectory = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
static let ArchiveURL = DocumentsDirectory.URLByAppendingPathComponent("scores")
struct PropertyKey {
static let highScoreKey = "high"
static let currentScoreKey = "current"
static let lifeTimeScoreKey = "life"
}
func encodeWithCoder(aCoder: NSCoder){
aCoder.encodeObject(score, forKey: PropertyKey.currentScoreKey)
aCoder.encodeObject(highScore, forKey: PropertyKey.highScoreKey)
aCoder.encodeObject(lifeTimeScore, forKey: PropertyKey.lifeTimeScoreKey)
}
required convenience init?(coder aDecoder: NSCoder) {
let score = aDecoder.decodeObjectForKey(PropertyKey.currentScoreKey) as! Int
let highScore = aDecoder.decodeObjectForKey(PropertyKey.highScoreKey) as! Int
let lifeTimeScore = aDecoder.decodeObjectForKey(PropertyKey.lifeTimeScoreKey) as! Int
self.init(score: score, highScore: highScore, lifeTimeScore: lifeTimeScore)
}
init?(score: Int, highScore: Int, lifeTimeScore: Int!) {
// Initialize stored properties.
self.score = score
self.highScore = highScore
self.lifeTimeScore = lifeTimeScore
super.init()
}
}
当我加载分数时出现问题。如果我删除了lifeTimeScore,那么一切正常。然而,一旦我尝试实施这个小傻瓜,他就会抛出一个
致命错误:在解包可选值时意外发现nil
当我检查调试器时,问题来自
let lifeTimeScore = aDecoder.decodeObjectForKey(PropertyKey.lifeTimeScoreKey) as! Int
真的很混乱,我真的处于停滞状态。这是调用Score类的GameModel类。当我用newGame()实例化它时。我收到了错误。
class GameModel: NSObject {
private var highScore = Int()
private var berriesCaught: Int = NO_BERRIES_CAUGHT
private var lifeTimeBerries = Int()
var gameOver: Bool!
var damaged: Bool!
func newGame(){
berriesCaught = NO_BERRIES_CAUGHT
if (loadScores() != nil) {
if let score = loadScores(){
highScore = score.highScore
lifeTimeBerries = score.lifeTimeScore
}
}
checkGameState()
damaged = false
}
func saveScores(){
checkHighScore()
lifeTimeBerries += berriesCaught
if let scoreToken = Score(score: berriesCaught, highScore: highScore, lifeTimeScore: lifeTimeBerries){
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(scoreToken, toFile: Score.ArchiveURL.path!)
if !isSuccessfulSave {
print("Failed to save scores")
}
}
}
func loadScores() -> Score? {
return NSKeyedUnarchiver.unarchiveObjectWithFile(Score.ArchiveURL.path!) as? Score
}
func checkHighScore(){
if let score = loadScores() {
if berriesCaught > score.highScore {
highScore = berriesCaught
} else {
highScore = score.highScore
}
} else{
highScore = berriesCaught
}
}
如何修复它以便在每场比赛后正确添加lifeTimeBerries? 我怎样才能修复它,以便在调用loadScores()时为属性加载正确的值?
感谢。
答案 0 :(得分:3)
您遇到崩溃的原因是,如果找不到密钥,解码密钥对象不会提供默认值(例如decodeBoolForKey默认为false)
因此您需要调整代码。正如另一位成员所说,将代码更改为
let lifeTimeScore = aDecoder.decodeIntegerForKey(PropertyKey.lifeTimeScoreKey)
如果没有找到密钥,将自动设置默认值,因为它知道您正在尝试解码整数。
如果你想使用decodeObjectForKey,你需要先做一些nil检查,因为没有默认值,因为你正在解码" AnyObject"。这条线
... as! Int
将强制将objectForKey解包为Int,但它可能不在那里,因此是nil而不是崩溃。要么改变它
if aDecoder.decodeObjectForKey(PropertyKey.lifeTimeScoreKey) != nil {
let lifeTimeScore = aDecoder.decodeObjectForKey(PropertyKey.lifeTimeScoreKey) as! Int
}
或使用这个方便的功能将其放在一行
let lifeTimeScore = aDecoder.decodeObjectForKey(PropertyKey.lifeTimeScoreKey) as? Int ?? Int()
这里它将检查一个键是否存在(如?Int),如果它没有,它将创建一个新的默认值(?? Int())。
最有可能最好的方法是使用IntegerForKey,因为你的" lifeTimeScore"是一个Int,只有你也可以使用ObjectForKey。
答案 1 :(得分:1)
使用此更新的代码和解码器方法。
func encodeWithCoder(aCoder: NSCoder){
aCoder.encodeInt(score, forKey: PropertyKey.currentScoreKey)
aCoder.encodeInt(highScore, forKey: PropertyKey.highScoreKey)
aCoder.encodeInt(lifeTimeScore, forKey: PropertyKey.lifeTimeScoreKey)
}
required convenience init?(coder aDecoder: NSCoder) {
let score = aDecoder.decodeIntForKey(PropertyKey.currentScoreKey)
let highScore = aDecoder.decodeIntForKey(PropertyKey.highScoreKey
let lifeTimeScore = aDecoder.decodeIntForKey(PropertyKey.lifeTimeScoreKey)
self.init(score: score, highScore: highScore, lifeTimeScore: lifeTimeScore)
}