NSKeyedUnArchiver 崩溃

Posted

技术标签:

【中文标题】NSKeyedUnArchiver 崩溃【英文标题】:NSKeyedUnArchiver Crash 【发布时间】:2016-11-29 14:40:48 【问题描述】:

我的应用程序委托由于 NSException 崩溃而崩溃。我使用异常断点工具来查明崩溃的位置(在其顶部添加了注释,在 init() 中)在 NSUarchiver 期间以及在一个名为 ItemStore.xml 的文件中。请帮我修复这个错误,我已经尝试了所有的想法。

没有异常断点,这就是崩溃

2016-11-29 09:46:42.546 Foodie[3100:386241] *** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (Photomania.Item) for key (NS.objects); the class may be defined in source code or a library that is not linked'

当我使用异常断点时,我在 ItemStore 下面的星号行收到异常。

ItemStore.swift:

import Foundation

class ItemStore 

var allItems: [Item] = []
let itemArchiveURL: NSURL = 
    let documentsDirectories =
    NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,
        inDomains: .UserDomainMask)
    let documentDirectory = documentsDirectories.first!
    return documentDirectory.URLByAppendingPathComponent("items.archive")
    ()

init() 

    // here is the crash
    if let archivedItems =
        NSKeyedUnarchiver.unarchiveObjectWithFile(itemArchiveURL.path!) as? [Item] 
            allItems += archivedItems
    


func moveItemAtIndex(fromIndex: Int, toIndex: Int) 
    if fromIndex == toIndex 
        return
    

    // Get reference to object being moved so you can re-insert it
    let movedItem = allItems[fromIndex]

    // Remove item from array
    allItems.removeAtIndex(fromIndex)

    // Insert item in array at new location
    allItems.insert(movedItem, atIndex: toIndex)


func createItem() -> Item 
    let newItem = Item(random: true)

    allItems.append(newItem)

    return newItem


func removeItem(item: Item) 
    if let index = allItems.indexOf(item) 
        allItems.removeAtIndex(index)
    


func saveChanges() -> Bool 
    print("Saving items to: \(itemArchiveURL.path!)")
    return NSKeyedArchiver.archiveRootObject(allItems, toFile: itemArchiveURL.path!)



应用代理:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate 

var window: UIWindow?

// Override point for customization after application launch.

//Create an ImageStore
//let imageStore = ImageStore()
//let itemStore = ItemStore()

//Access the ItemsViewController and set its item store
//let navController = window!.rootViewController as! UINavigationController
//let itemsController = navController.topViewController as! ItemsViewController

//itemsController.itemStore = itemStore
//itemsController.imageStore = imageStore

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 

    let rootController = window?.rootViewController

    if rootController is UITabBarController 
        let firstTabItem = (rootController as! UITabBarController).viewControllers?[0]

        if firstTabItem is UINavigationController 

            let firstController = (firstTabItem as! UINavigationController).viewControllers.first as! ItemsViewController
            firstController.itemStore  = ItemStore()
            firstController.imageStore = ImageStore()
        
    
    return true


...


Photomania.Item:

import UIKit

class Item: NSObject, NSCoding 

var meal: String
var restaurantName: String?
var valueInDollars: Int
let dateCreated: NSDate
let itemKey: String

init(meal: String, restaurantName: String?, valueInDollars: Int) 
    self.meal = meal
    self.restaurantName = restaurantName
    self.valueInDollars = valueInDollars
    self.dateCreated = NSDate()
    self.itemKey = NSUUID().UUIDString


convenience init(random: Bool = false) 
    if random 
        let nouns = ["Meal"]
        let places = ["Restaurant"]

        var idx = arc4random_uniform(UInt32(nouns.count))
        let randomNoun = nouns[Int(idx)]

        idx = arc4random_uniform(UInt32(places.count))
        let randomPlace = places[Int(idx)]

        let randomName = "\(randomNoun)"
        let randomValue = Int(arc4random_uniform(100))
        let randomRestaurantName = "\(randomPlace)"

        self.init(meal: randomName,
            restaurantName: randomRestaurantName,
            valueInDollars: randomValue)
    
    else 
        self.init(meal: "", restaurantName: nil, valueInDollars: 0)
    


    required init(coder aDecoder: NSCoder) 
    meal = aDecoder.decodeObjectForKey("meal") as! String
    dateCreated = aDecoder.decodeObjectForKey("dateCreated") as! NSDate
    itemKey = aDecoder.decodeObjectForKey("itemKey") as! String
    restaurantName = aDecoder.decodeObjectForKey("restaurantName") as! String?

    valueInDollars = aDecoder.decodeIntegerForKey("valueInDollars")

    super.init()


    func encodeWithCoder(aCoder: NSCoder) 
        aCoder.encodeObject(meal, forKey: "meal")
        aCoder.encodeObject(dateCreated, forKey: "dateCreated")
        aCoder.encodeObject(itemKey, forKey: "itemKey")
        aCoder.encodeObject(restaurantName, forKey: "restaurantName")

        aCoder.encodeInteger(valueInDollars, forKey: "valueInDollars")
    


【问题讨论】:

请发布崩溃的完整细节。引发的异常是什么?什么是完整的错误和回溯? @JAL 我用详细信息编辑了我的问题。 什么是Photomania.Item @JAL 我项目中的另一个文件。该应用程序允许用户在 UITableView 中创建项目并上传它的图片。 【参考方案1】:

你没有显示你的 Photomania.Item 类/结构,但它应该符合 NSCoding 协议。看看这个例子: http://mhorga.org/2015/08/25/ios-persistence-with-nscoder-and-nskeyedarchiver.html

【讨论】:

我不明白这如何适用于我的班级。我试图插入示例材料,但有很多错误。我将原始 Photomania.Item 类添加到问题的底部。 你又添加了ItemStore,我没有看到Item类 我修好了。对不起 尝试删除您的应用并在您的保存数据已损坏时运行 什么意思?如何删除我的应用?

以上是关于NSKeyedUnArchiver 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Swift 防止 NSKeyedUnarchiver.decodeObject 崩溃的唯一方法?

设置基础 SDK 后,iPhone 模拟器在 NSKeyedUnarchiver 中崩溃

错误处理 - NSKeyedUnarchiver

在到达我的代码之前,应用程序在运行时崩溃 xcode6.1 Universal App Objective-C NSKeyedUnarchiver iOS 7.0 iOS 8.1

捕获 NSKeyedUnarchiver 异常

NSKeyedUnarchiver.unarchiveObject 不工作 [重复]