这是我的 Game 对象的代码。它有很多不同的属性,其中一个是 Cards 的数组。当我尝试使用NSCoding保存我的游戏对象时,XCode会抛出此错误
***由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:' - [Hearthstone_Tracker.Card encodeWithCoder:]:无法识别的选择器发送到实例0x7fbca9db9750'
从我读过的内容来看,这些错误经常发生在UIButton调用函数时,并在函数不期望它时将自身作为参数传递,反之亦然。我不知道它如何适用于我的情况。
我读过NSCoding有一些结构问题,但由于卡实际上是一个类,我不认为问题就在那里。
这是我的游戏类:
import Foundation
import UIKit
class Game: NSObject, NSCoding {
// MARK: Properties
let playerHero: String
let playerDeck: String
let playerImage: UIImage?
let opponentHero: String
let opponentDeck: String
let opponentImage: UIImage?
let result: String
let coin: Bool
var date: String?
let mode: String
let rank: String?
let duration: Int?
let durationSec: Int?
let id: Int
let cardsPlayed: [Card]
var manaEfficiency: (Double, Double)?
var turnCount: Int?
var estimatedTurnLength: Int?
var finisher: String?
// MARK: Keys for the data
struct PropertyKey {
static let playerHero = "playerHero"
static let playerDeck = "playerDeck"
static let playerImage = "playerImage"
static let opponentHero = "opponentHero"
static let opponentDeck = "opponentDeck"
static let opponentImage = "opponntImage"
static let result = "result"
static let coin = "coin"
static let date = "date"
static let mode = "mode"
static let rank = "rank"
static let duration = "duration"
static let durationSec = "durationSec"
static let id = "id"
static let cardsPlayed = "cardsPlayed"
}
// MARK: Archiving Paths
static let DocumentsDirectory: AnyObject = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
static let ArchiveURL = DocumentsDirectory.URLByAppendingPathComponent("games")
// MARK: Initializer
init(playerHero: String, playerDeck: String, opponentHero: String, opponentDeck: String, result: String, coin: Bool, date: String, mode: String, rank: String, duration: Int?, durationSec: Int?, id: Int, cardsPlayed: [Card]) {
// ...
// Some initializer code
// ...
self.cardsPlayed = cardsPlayed
super.init()
}
// MARK: NSCoding
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(playerHero, forKey: PropertyKey.playerHero)
aCoder.encodeObject(playerDeck, forKey: PropertyKey.playerDeck)
aCoder.encodeObject(opponentHero, forKey: PropertyKey.opponentHero)
aCoder.encodeObject(opponentDeck, forKey: PropertyKey.opponentDeck)
aCoder.encodeObject(result, forKey: PropertyKey.result)
aCoder.encodeBool(coin, forKey: PropertyKey.coin)
aCoder.encodeObject(date, forKey: PropertyKey.date)
aCoder.encodeObject(mode, forKey: PropertyKey.mode)
aCoder.encodeObject(rank, forKey: PropertyKey.rank)
aCoder.encodeObject(duration, forKey: PropertyKey.duration)
aCoder.encodeObject(durationSec, forKey: PropertyKey.durationSec)
aCoder.encodeObject(id, forKey: PropertyKey.id)
aCoder.encodeObject(cardsPlayed, forKey: PropertyKey.cardsPlayed)
}
required convenience init?(coder aDecoder: NSCoder) {
let playerHero = aDecoder.decodeObjectForKey(PropertyKey.playerHero) as! String
let playerDeck = aDecoder.decodeObjectForKey(PropertyKey.playerDeck) as! String
let opponentHero = aDecoder.decodeObjectForKey(PropertyKey.opponentHero) as! String
let opponentDeck = aDecoder.decodeObjectForKey(PropertyKey.opponentDeck) as! String
let result = aDecoder.decodeObjectForKey(PropertyKey.result) as! String
let coin = aDecoder.decodeBoolForKey(PropertyKey.coin)
let date = aDecoder.decodeObjectForKey(PropertyKey.date) as! String
let mode = aDecoder.decodeObjectForKey(PropertyKey.mode) as! String
let rank = aDecoder.decodeObjectForKey(PropertyKey.rank) as! String
let duration = aDecoder.decodeObjectForKey(PropertyKey.duration) as? Int
let durationSec = aDecoder.decodeObjectForKey(PropertyKey.durationSec) as? Int
let id = aDecoder.decodeObjectForKey(PropertyKey.id) as! Int
let cardsPlayed = aDecoder.decodeObjectForKey(PropertyKey.cardsPlayed) as! [Card]
self.init(playerHero: playerHero, playerDeck: playerDeck, opponentHero: opponentHero, opponentDeck: opponentDeck, result: result, coin: coin, date: date, mode: mode, rank: rank, duration: duration, durationSec: durationSec, id: id, cardsPlayed: cardsPlayed)
}
这是卡类:
import Foundation
import UIKit
class Card: NSObject {
// MARK: Properties
let name: String
let manacost: Int
let turn: Int
let player: String
// MARK: Initialzer
init(name: String, manacost: Int, turn: Int, player: String) {
self.name = name
self.manacost = manacost
self.turn = turn
self.player = player
super.init()
}
}
答案 0 :(得分:2)
每个对象(及其内部子对象 的层次结构)能够存储在NSDefaults
中必须能够序列化本身......那是......必须符合NSCoding
。