这是xcode的错误抛出:
由于未捕获的异常而终止应用 ' NSInvalidUnarchiveOperationException',原因:' *** - [NSKeyedUnarchiver decodeInt64ForKey:]:key(rating)的值不是整数'
这是创建Meal对象的类的一部分:
// MARK:属性
var rating: Int var name: String var photo: UIImage?
// MARK:路径
static let DocumentDirectory = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains:.UserDomainMask).first! static let ArchivelUrl = DocumentDirectory.URLByAppendingPathComponent("meals")
// MARK:NSCoding
func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(name, forKey: propertyKey.nameKey) aCoder.encodeObject(photo, forKey: propertyKey.photoKey) aCoder.encodeInteger(rating, forKey: propertyKey.ratingKey) } required convenience init?(coder aDecoder: NSCoder) { let name = aDecoder.decodeObjectForKey(propertyKey.nameKey) as! String let photo = aDecoder.decodeObjectForKey(propertyKey.photoKey) as? UIImage let rating = aDecoder.decodeIntegerForKey(propertyKey.ratingKey) //must call to designate initiallizer self.init(name: name,photo: photo,rating: rating) }
这是归档者和unarchiver:
// MARK:NSCoding
func saveMeal(){ let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(meals, toFile:Meal.ArchivelUrl.path!) if !isSuccessfulSave { print("Failed to save") } else{ print("saved") } } func loadMeal() -> [Meal]? { return NSKeyedUnarchiver.unarchiveObjectWithFile(Meal.ArchivelUrl.path!) as [Meal] }
我在苹果网站上关注了本教程:[https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson10.html
示例项目有效。我试图将我的代码复制到他们的项目文件中,它也有效。所以我认为这里有不同的设置!
答案 0 :(得分:17)
我通过替换以下代码解决了这个问题:
let rating = aDecoder.decodeIntegerForKey(propertyKey.ratingKey)
to
let rating = aDecoder.decodeObjectForKey(propertyKey.ratingKey) as! Int
我猜你之前已经编译并保存了对象而不是Integer,所以当你将对象解码为Integer时,它会告诉你对象不是Integer(导致编译器不知道对象类型是什么)< / p>
或者您可以打印Meal.ArchivelUrl.path!
并删除现有的meal.text
,然后在模拟器中删除该应用,然后再编译您在此处发布的代码。我认为这样会好的(对我来说至少没问题)。
答案 1 :(得分:6)
好吧所以我终于弄明白了这个问题。在存储值时,optional
值被编码。并且由于swift编码器功能即使在仅接受整数的函数上传递非整数值时也不会发出任何警告。
解决方案是使用Int
对!
值进行编码。
查看我的课程了解更多详情。请注意,Permission
和Office
是类。
class User : NSObject, NSCoding {
var bio : String! = ""
var careerLevel : Int! = 0
var office : Office!
var permissions : Array<Permission>!
init (userDetail:Dictionary<String, Any>) {
super.init()
//set values
self.setValues(detail: userDetail)
}
func setValues(detail:Dictionary<String, Any>) {
if let value = detail["hash_token"] as? String {self.accessToken = value}
//now get user detail
if var information = detail["user_details"] as? Dictionary<String, Any> {
if let value = information["bio"] {self.bio = String(describing: value)}
if let value = information["career_level"] {self.careerLevel = Int(String.init(describing: value))!}
//set office information
if let officeDictionary = information["office_detail"] as? Dictionary<String, Any> {
let office_ = Office.init(detail: officeDictionary, id: officeId)
self.office = office_
}
//now set permission information
if self.permissions != nil {self.permissions.removeAll(); self.permissions = nil}
self.permissions = Array<Permission>()
if let permissionArray = information["permissions"] as? Array<Any>{
for permissionDictionary in permissionArray {
let permission : Permission = Permission.init(detail: permissionDictionary as! Dictionary<String, Any>)
self.permissions.append(permission)
}
}
}
}
required init(coder decoder: NSCoder) {
//Error here "missing argument for parameter name in call
self.bio = decoder.decodeObject(forKey: "bio") as! String
self.careerLevel = decoder.decodeInteger(forKey: "careerLevel")
//
self.office = decoder.decodeObject(forKey: "office") as! Office
self.permissions = decoder.decodeObject(forKey: "permissions") as! Array<Permission>
super.init()
}
func encode(with aCoder: NSCoder) {
//
aCoder.encode(self.bio!, forKey: "bio")
aCoder.encode(self.careerLevel!, forKey:"careerLevel")
//
aCoder.encode(self.office!, forKey: "office")
aCoder.encode(self.permissions!, forKey: "permissions")
}
}
答案 2 :(得分:0)
This GitHub issue建议一种修复方法是在Simulator应用程序中进行Hardware > Erase all Content and Settings