我只是尝试在Swift中进行编码,并且尝试在Apple Dev Library re:Meals中修改此现有项目。
我希望将其他子类(例如“成分”)放到主餐类中,将其作为数组或成分。
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)
}
}
用于保存和加载膳食项目的函数调用如下:
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'“
我能知道如何成功地将Ingredients数组包含到保存的对象中吗?
答案 0 :(得分:0)
您必须实现NSCoding
协议
func encode(with aCoder: NSCoder) {}
required convenience init?(coder aDecoder: NSCoder) {}
还在内部自定义类中
class Ingredients: NSObject , NSCoding {}