【问题标题】:How to save objects with sub-classes using NSKeyedArchiver in Swift IOS如何在 Swift IOS 中使用 NSKeyedArchiver 保存带有子类的对象
【发布时间】:2018-09-10 12:32:36
【问题描述】:

我只是在尝试使用 Swift 进行编码,并且我正在尝试在 Apple Dev Library re: Meals 中修改这个现有项目。

我希望在主 Meal 类中添加一个额外的子类,例如成分,并将其作为一个数组或成分。

import UIKit
import os.log

class Meal: NSObject, NSCoding {

    //MARK: Properties

    var name: String
    var photo: UIImage?
    var rating: Int
    var recipe: [ingredients]?

    //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"
        static let recipe = "recipe"
    }

    //MARK: Initialization

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

        // 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
        self.recipe = recipe
    }

    //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)
        aCoder.encode(recipe, forKey: PropertyKey.recipe)
    }

    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 {
            os_log("Unable to decode the name for a Meal object.", log: OSLog.default, type: .debug)
            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)

        let recipe = aDecoder.decodeObject(forKey: PropertyKey.recipe)

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

    }
}

保存和加载Meal项目的函数调用如下:

   private func saveMeals() {
        let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(meals, toFile: Meal.ArchiveURL.path)
        if isSuccessfulSave {
            os_log("Meals successfully saved.", log: OSLog.default, type: .debug)
        } else {
            os_log("Failed to save meals...", log: OSLog.default, type: .error)
        }
    }

    private func loadMeals() -> [Meal]?  {
        return NSKeyedUnarchiver.unarchiveObject(withFile: Meal.ArchiveURL.path) as? [Meal]
    }

我声明了一个新的 Class Ingredients.swift 来捕获我想要的成分。

import UIKit
import os.log

class Ingredients: NSObject {

    struct PropertyKey {
        static let name = "name"
        static let  quantity = "quantity"
    }

    var name: String!
    var quantity: Double!

    //MARK: Initialization

    init?(name: Int, quantity: Double) {

        self.name = name
        self.quantity = quantity
    }
}

我现在遇到的问题是 XCode 抛出“由于未捕获的异常而终止应用程序

'NSInvalidArgumentException',原因:'-[MealTracker.Ingredients encodeWithCoder:]:无法识别的选择器发送到实例 0x1c40a0e40'"

我能否知道如何成功地将成分数组包含到保存的对象中?

【问题讨论】:

    标签: ios iphone swift database nskeyedarchiver


    【解决方案1】:

    你必须实现NSCoding协议

    func encode(with aCoder: NSCoder) {}
    required convenience init?(coder aDecoder: NSCoder) {}
    

    内部自定义类也是

    class Ingredients: NSObject , NSCoding {}
    

    【讨论】:

    • 您也可以使用 Codable 更快捷的方式
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    相关资源
    最近更新 更多