#swift #unrecognized-selector #nskeyedarchiver
#swift #нераспознанный селектор #nskeyedarchiver
Вопрос:
Я слежу за демонстрацией FoodTracker у разработчика Apple. Я перехожу к последнему разделу: сохранение данных.
Я запускаю Xcode 8 и слежу за демонстрационной сборкой на Swift 3.
Если я загружу код и конвертирую в Swift 2.3, это не сработает. Если я перейду на Swift 3.0, это тоже не сработает. Я пытался следить за демонстрацией на Swift 3.
Код требует некоторых изменений для компиляции и запуска на Swift 3, и до сих пор я добивался успеха.
Однако теперь я получаю это во время выполнения:
FoodTracker [1597:720222] *** Завершающее приложение из-за неперехваченного исключения ‘NSInvalidArgumentException’, причина: ‘ [NSKeyedArchiver unarchiveObjectWithFile:]: нераспознанный селектор, отправленный в класс 0x1081497a8’
Изменения, которые я должен был внести в этот раздел, заключались в следующем: 1) В классе Meal я добавил две статические константы:
static let DocumentsDirectory =
FileManager().urls(for: .documentDirectory, in:
.userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("meals")
2) Также в классе Meal я добавил struct и удобный init:
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: PropertyKey.nameKey)
aCoder.encode(photo, forKey: PropertyKey.photoKey)
aCoder.encode(rating, forKey: PropertyKey.ratingKey)
}
required convenience init?(coder aDecoder: NSCoder) {
let name = aDecoder.decodeObject(forKey: PropertyKey.nameKey) as! String
// Because photo is an optional property of Meal, use conditional cast
let photo = aDecoder.decodeObject(forKey: PropertyKey.photoKey) as? UIImage
let rating = aDecoder.decodeInteger(forKey: PropertyKey.ratingKey)
// Must call designated initializer
self.init(name: name, photo: photo, rating: rating)
}
3) В классе MealTableViewController я добавил функции saveMeals и loadMeals:
func saveMeals() {
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(meals, toFile: Meal.ArchiveURL.path)
if !isSuccessfulSave {
print("Failed to save meals...")
}
}
func loadMeals() -> [Meal]? {
return NSKeyedArchiver.classForKeyedUnarchiver().unarchiveObject(withFile: Meal.ArchiveURL.path) as? [Meal]
}
Код успешно компилируется, но во время выполнения происходит сбой. Строка 5 ошибки stacktrace, похоже, указывает на класс Meal и метод loadMeals в качестве виновника:
5 FoodTracker 0x0000000107ce9e44 _TFC11FoodTracker23MealTableViewController9loadMealsfT_GSqGSaCS_4Meal__ 276
6 FoodTracker 0x0000000107ce701a _TFC11FoodTracker23MealTableViewController11viewDidLoadfT_T_ 266
7 FoodTracker 0x0000000107ce7222 _TToFC11FoodTracker23MealTableViewController11viewDidLoadfT_T_ 34
К сожалению, на данный момент я не знаю больше, чтобы следить за панировочными сухарями, которые Xcode и Swift оставляют для меня. Просто пытаюсь узнать из источника (разработчики Apple).
Я выполнил поиск в Интернете и на этом сайте, но не совсем нашел ответ, который я смог бы использовать для решения проблемы. Это последний раздел руководства, и я действительно хотел бы его завершить. Спасибо вам за любую помощь, которую вы можете предоставить; Я надеюсь оплатить ее вперед, как только освоюсь с Swift. Спасибо!
Ответ №1:
Использовать NSKeyedUnarchiver
:
func loadMeals() -> [Meal]? {
return NSKeyedUnarchiver.unarchiveObject(withFile: Meal.ArchiveURL.path) as? [Meal]
}
Комментарии:
1. Спасибо! Это именно то, что это было. Теперь, когда я просматриваю код руководства, я вижу, что NSKeyeedUnarchiver действительно указан… Должно быть, я выбрал неправильную опцию автозаполнения, а затем не смог определить разницу в ключевых словах. Я должен уделять больше внимания деталям кода, которые боюсь признать.