xcode NSInvalidUnarchiveOperationException,当尝试unarchive文件时

del*_*los 3 xcode ios

这是xcode的错误抛出:

由于未捕获的异常'NSInvalidUnarchiveOperationException'而终止应用程序,原因:'*** - [NSKeyedUnarchiver decodeInt64ForKey:]:键的值(评级)不是整数'

这是创建Meal对象的类的一部分:

// MARK:属性

var rating: Int
var name: String
var photo: UIImage?
Run Code Online (Sandbox Code Playgroud)

// MARK:Path

static let DocumentDirectory = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains:.UserDomainMask).first!

static let ArchivelUrl = DocumentDirectory.URLByAppendingPathComponent("meals")
Run Code Online (Sandbox Code Playgroud)

// 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)
}
Run Code Online (Sandbox Code Playgroud)

这是归档者和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] }
Run Code Online (Sandbox Code Playgroud)

我在苹果网站上关注了这个教程:[ https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson10.html

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

Jer*_* Li 19

我通过替换以下代码解决了这个问题:

let rating = aDecoder.decodeIntegerForKey(propertyKey.ratingKey)
to
let rating = aDecoder.decodeObjectForKey(propertyKey.ratingKey) as! Int
Run Code Online (Sandbox Code Playgroud)

我猜你之前已经编译并保存了对象而不是Integer,所以当你将对象解码为Integer时,它会告诉你对象不是Integer(导致编译器不知道对象类型是什么)

或者您可以打印Meal.ArchivelUrl.path!并删除现有的meal.text,并在模拟器中删除应用程序,然后再编译您在此处发布的代码.我认为这样会好的(对我来说至少没问题).


rpt*_*thi 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")
    }
}
Run Code Online (Sandbox Code Playgroud)