NSKeyedUnarchiver返回nil - 无法将'MyProj.Meal'(0x105373f68)类型的值转换为'MyProj.Meal'(0x11f5ee928)

时间:2017-07-27 23:00:51

标签: ios swift nskeyedarchiver nskeyedunarchiver

我正试图摆脱归档对象。我正在关注Apple的示例项目持久性:https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/PersistData.html

基本上有一个符合NSCoding协议的Meal类。但是,当我运行测试来存档/取消归档此Meal对象时,我收到以下错误:

Could not cast value of type 'MyProj.Meal' (0x105373f68) to 'MyProj.Meal' (0x11f5ee928)

这是产生错误的代码;错误发生在第三行:

let meal = Meal(name: "food", photo: nil, rating: 4)!
let data = NSKeyedArchiver.archivedData(withRootObject: meal)
let unarchivedMeal = NSKeyedUnarchiver.unarchiveObject(with: data) as! Meal

XCTAssertNotNil(unarchivedMeal)

以下是Apple的餐饮课程:

//
//  Meal.swift
//  FoodTracker
//
//  Created by Jane Appleseed on 11/10/16.
//  Copyright © 2016 Apple Inc. All rights reserved.
//

import UIKit
import os.log

class Meal: NSObject, NSCoding {

//MARK: Properties

var name: String
var photo: UIImage?
var rating: Int

//MARK: Archiving Paths
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("meals")

//MARK: Types

struct PropertyKey {
    static let name = "name"
    static let photo = "photo"
    static let rating = "rating"
}

//MARK: Initialization

init?(name: String, photo: UIImage?, rating: Int) {

    // The name must not be empty
    guard !name.isEmpty else {
        return nil
    }

    // The rating must be between 0 and 5 inclusively
    guard (rating >= 0) && (rating <= 5) else {
        return nil
    }

    // Initialization should fail if there is no name or if the rating is negative.
    if name.isEmpty || rating < 0  {
        return nil
    }

    // Initialize stored properties.
    self.name = name
    self.photo = photo
    self.rating = rating

}

//MARK: NSCoding

func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: PropertyKey.name)
    aCoder.encode(photo, forKey: PropertyKey.photo)
    aCoder.encode(rating, forKey: PropertyKey.rating)
}

required convenience init?(coder aDecoder: NSCoder) {

    // The name is required. If we cannot decode a name string, the initializer should fail.
    guard let name = aDecoder.decodeObject(forKey: PropertyKey.name) as? String else {
        debugPrint("Unable to decode the name for a Meal object.")
        return nil
    }

    // Because photo is an optional property of Meal, just use conditional cast.
    let photo = aDecoder.decodeObject(forKey: PropertyKey.photo) as? UIImage

    let rating = aDecoder.decodeInteger(forKey: PropertyKey.rating)

    // Must call designated initializer.
    self.init(name: name, photo: photo, rating: rating)

    }
}

有什么想法吗?这真是令人沮丧

0 个答案:

没有答案