【问题标题】:NSUserdefaults decoder results in NSArray element failed to match the Swift Array Element typeNSUserdefaults 解码器导致 NSArray 元素无法匹配 Swift Array 元素类型
【发布时间】:2017-03-01 19:51:54
【问题描述】:

我试图从 NSUserDefaults 创建一个数组。旧应用程序位于 Obj C 中,我认为我的 userdefaults 文件类型为 NSArray,该数组包含一个名为 GD_Owed_HistoryObject 的自定义类。

我尝试解码这个类并使用 Swift 3 在新应用中使用它

@objc(GD_Owed_HistoryObject)
class UserDefaultHistory: NSObject, NSCoding {

let saveDate: String?

init(saveDate: String) {
    self.saveDate = saveDate
}

required init(coder decoder: NSCoder) {
    self.saveDate = (decoder.decodeObject(forKey: "owedSaveDate") as? String)
}

func encode(with coder: NSCoder) {
    coder.encode(saveDate, forKey: "owedSaveDate")
}
}

我可以得到我的数组的计数,并且其中包含正确数量的对象

print("\(statementHistory.count) is the array count") // 3

我还试图弄清楚我的数组中有哪些类型的对象

print("\(type(of: statementHistory)) type of array") // UserDefaultStatement

UserDefaultStatement 是我假设我从 NSUserdefaults 中得到的。所以我尝试用它来创建数组

import UIKit

@objc(GD_Owed_Bill)
class UserDefaultStatement: NSObject, NSCoding {
    var statementHistory: [UserDefaultHistory]

    init(statementHistory: UserDefaultHistory) {
        self.statementHistory = [statementHistory]
    }

    required init(coder decoder: NSCoder) {
        self.statementHistory = (decoder.decodeObject(forKey: "owedHistoryArray") as! Array)
    }

    func encode(with coder: NSCoder) {
        coder.encode(statementHistory, forKey: "owedHistoryArray")

    }

}

但是当我尝试访问 UserDefaultHistory 上的属性时,我收到了这个错误。

fatal error: NSArray element failed to match the Swift Array Element type
2017-03-01 11:58:37.411214 owed[1230:571980] fatal error: NSArray element failed to match the Swift Array Element type

我已经为此工作了 2 天,但没有取得任何进展。我认为我分配的数组类型不正确,但我不知道如何询问我从解码中返回的对象类型。

更新 在使用旧应用程序一段时间后,我似乎 NSKeyArchived 对象,根据我需要做什么来使用它们来判断。

historyArray = [NSArray arrayWithArray:billDetails.historyArray];
NSLog(@"This is the array count for the history log %lu", (unsigned long)historyArray.count);

// check to see if there is history
[self checkHistory];

// un archive the history array objects
for (NSData *historyData in historyArray)
{
    // set a instance of the person class to each NSData object found in the temp array
    GD_Owed_HistoryObject *historyObject = [[GD_Owed_HistoryObject alloc] init];
    historyObject = [NSKeyedUnarchiver unarchiveObjectWithData:historyData];
    NSLog(@"This is the history object %@", historyObject);
    NSLog(@"This is the save date %@", historyObject.saveDate);
    NSLog(@"This is the total before %@", historyObject.beforeTotal);
    NSLog(@"This is the total after %@", historyObject.afterTotal);
    NSLog(@"This is the amount changed %@", historyObject.amountChanged);
    //[decodedHistoryArray addObject: historyObject];

    [decodedHistoryArray insertObject:historyObject atIndex:0];
}

我现在完全确定如何将包含存档对象的数组取出并取消存档。 statementHistory 将是我的包含存档项目的数组

更新

var historyArray = statementHistory

            let restoredStatement = NSKeyedUnarchiver.unarchiveObject(with: historyArray) as! UserDefaultHistory
            restoredStatement.statementHistory[0].saveDate

但我收到此错误: Cannot convert value ot type '[UserDefaultHistory]' ot expected argument type 'Data'

【问题讨论】:

    标签: xcode swift3 nsuserdefaults nscoding


    【解决方案1】:

    问题中的代码基本有效。错误一定在其他地方。

    我在 Playground 中测试了这段代码,也许它是如何使用归档器/取消归档器的提示:

    let defaultHistory = UserDefaultHistory(saveDate: "2017/3/1")
    let statement = UserDefaultStatement(statementHistory: defaultHistory)
    
    // archive the class to Data
    let data = NSKeyedArchiver.archivedData(withRootObject: statement)
    print(data as NSData) // the type cast prints the raw data rather than "xy bytes"
    
    // unarchive the data to class
    let restoredStatement = NSKeyedUnarchiver.unarchiveObject(with: data) as! UserDefaultStatement
    restoredStatement.statementHistory[0].saveDate // "2017/3/1"
    

    PS:正如您在上一个问题中提到的那样,您将存档[UserDefaultHistory],因此您肯定会得到[UserDefaultHistory] (decodeObject(forKey: "owedHistoryArray") as! [UserDefaultHistory]))。在UserDefaultHistory 中您将始终拥有一个非可选字符串。完全不需要使用可选项。

    【讨论】:

    • 我想我正在取得一些进展!查看原始代码后,似乎数组中的对象是 NSKeyArchived,我不确定这样的事情是否会导致致命错误。我会更新我发现的问题
    • 使用我的示例如何应用 unarchiver。 historyArray 在 Swift 中是 [Data]
    • 如果数据已经存档,我需要使用它怎么办?
    • 我用我认为你告诉我的内容更新了问题,但我知道我没有正确的东西。
    • Sigh dataArray 到底是从哪里来的?在您的最新更新中historyArray 已经是[UserDefaultHistory](告诉错误消息),您无需取消归档。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2015-09-27
    • 1970-01-01
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    相关资源
    最近更新 更多