Xcode NSInvalidUnarchiveOperationException when trying to unpack a file
This is the error with xcode:
Application terminated due to uncaught exception "NSInvalidUnarchiveOperationException", reason: "*** - [NSKeyedUnarchiver decodeInt64ForKey:]: value for key (rating) is not an integer"
This is part of the class for creating the Meal object:
// MARK: Properties
var rating: Int var name: String var photo: UIImage?
// MARK: Path
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) }
and this is an archiver and an 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] }
I followed this tutorial on apple site: [ https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson10.html
The sample project worked. I tried to copy the code into my project files and it worked too. So I think there is a difference here!
source to share
The problem I solved by replacing the following code:
let rating = aDecoder.decodeIntegerForKey(propertyKey.ratingKey)
to
let rating = aDecoder.decodeObjectForKey(propertyKey.ratingKey) as! Int
I think you have already compiled and stored the rating as an object instead of Integer, so when you decode the object as Integer it will tell you that the object is not Integer (the reason why the compiler doesn't know what the type of the object is)
Or you can print Meal.ArchivelUrl.path!
and delete the existing meal.text
and delete the application in your simulator and then Compile your code that you posted here again. I think it will be good (at least great for me).
source to share
Ok So I finally solved the problem. When a value optional
was obtained, encoding was obtained while storing the value. And since the fast encoding function does not raise any warning, even if odd values ββare passed to a function that is only meant to accept an integer.
The solution is to encode the value Int
with !
.
Check out my class for more details. Note that Permission
both Office
are classes.
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")
}
}
source to share
This GitHub issue suggests it can be fixed Hardware > Erase all Content and Settings
from within the Simulator app
source to share