xcode NSInvalidUnarchiveOperationException,当尝试unarchive文件时

时间:2015-06-27 08:12:05

标签: ios xcode

这是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

示例项目有效。我试图将我的代码复制到他们的项目文件中,它也有效。所以我认为这里有不同的设置!

3 个答案:

答案 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!值进行编码。

查看我的课程了解更多详情。请注意,PermissionOffice是类。

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