Ios 尝试将非属性列表对象插入NSUserDefaults

Ios 尝试将非属性列表对象插入NSUserDefaults,ios,swift,Ios,Swift,我不清楚为什么我不能将其保存到userprefs,方法是: /** save the queue to prefs so it can be processed at a later time */ func saveBackgroundNotificationsToPrefs(_ backgroundNotification:[Date:[App:NotificationSpecification]]) { UserDefaults.standard.set(backgroundNot

我不清楚为什么我不能将其保存到userprefs,方法是:

/** save the queue to prefs so it can be processed at a later time */
func saveBackgroundNotificationsToPrefs(_ backgroundNotification:[Date:[App:NotificationSpecification]]) {
    UserDefaults.standard.set(backgroundNotification, forKey: PreferencesModel.constants.backgroundNotificationsKey)
}
我保存的通知规范对象是:

internal var apps: [App] // this one saves in it's "saveAppsToPrefs" method

internal var backgroundNotifications: [Date:[App:NotificationSpecification]] // this one does not save.
我的应用程序结构是

struct App: Hashable, Codable, Equatable {
    let name: String
    let notify: String
    let id: String
    let isSubscribed: Bool
}
通知规范是:

struct NotificationSpecification: Hashable, Codable {
    let id: String // is also the app id
    let p8: String
    let key_id: String?
    let team_id: String?
    let topic: String
    let custom_endpoint: String?
    let custom_method: String?
    let custom_headers: [String:String]?

    init (id:String, p8:String, key_id:String, team_id:String, topic:String) {
        self.id = id
        self.p8 = p8
        self.key_id = key_id
        self.team_id = team_id
        self.topic = topic

        self.custom_endpoint = nil
        self.custom_method = nil
        self.custom_headers = nil

    }

    init (id:String, p8:String, topic:String, custom_endpoint:String, custom_method:String, custom_headers:[String:String]?) {
        self.id = id
        self.p8 = p8
        self.topic = topic
        self.custom_endpoint = custom_endpoint
        self.custom_method = custom_method
        self.custom_headers = custom_headers

        self.key_id = nil
        self.team_id = nil
    }
}
我收到的错误是:

2019-04-27 12:58:54.812658-0400 Behavior-based Notifications[15130:4568207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object {
    "" =     {
        "Behavior_based_Notifications.App(name: \"APP_NAME\", notify: \"{\\\"token\\\":\\\"APP_TOKEN\\\",\\\"body\\\":{\\\"to\\\":\\\"APP_TOKEN\\\",\\\"badge\\\":0,\\\"_category\\\":\\\"APP_CATEGORY\\\"}}\", id: \"APP_ID\", isSubscribed: true)" = "Behavior_based_Notifications.NotificationSpecification(id: \"SAME_APP_ID\", p8: \"custom\", key_id: nil, team_id: nil, topic: \"TOPIC\", custom_endpoint: Optional(\"HOST_URL"), custom_method: Optional(\"POST\"), custom_headers: Optional([\"host\": \"HOSTNAME\", \"content-type\": \"application/json\", \"accept-encoding\": \"gzip, deflate\", \"accept\": \"application/json\"]))";
    };
} for key backgroundNotification'
是因为自定义的_头吗?对此我能做些什么——我必须手动将其转换为json或从json转换为json吗

编辑 根据Larme的建议:

/** save the queue to prefs so it can be processed at a later time */
func saveBackgroundNotificationsToPrefs(_ backgroundNotification:[Date:[App:NotificationSpecification]]) {
    UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: backgroundNotification), forKey: PreferencesModel.constants.backgroundNotificationsKey)
}

/** restore the queue from prefs so it can be processed at a later time */
func getBackgroundNotificationFromPrefs() -> [Date:[App:NotificationSpecification]] {
    let defaultBackgroundNotification:[Date:[App:NotificationSpecification]] = [:]

    guard let backgroundNotificationData = UserDefaults.standard.value(forKey:
            PreferencesModel.constants.backgroundNotificationsKey) as? Data else {
        saveBackgroundNotificationsToPrefs(defaultBackgroundNotification)
        return defaultBackgroundNotification
    }

    guard let backgroundNotification = NSKeyedUnarchiver.unarchiveObject(with: backgroundNotificationData) as? [Date :
            [App:NotificationSpecification]] else {
        return defaultBackgroundNotification
    }

    return backgroundNotification
}
我得到:

“archivedData(withRootObject:)”在iOS 12.0中被弃用:使用+archivedDataWithRootObject:requiringSecureCoding:错误:取而代之

“unarchiveObject(with:)”在iOS 12.0中被弃用:使用+UnarchiveObjectOfClass:fromData:error:取而代之

如果我将其更改为
NSKeyedArchiver.archivedDataWithRootObject(backgroundNotification)


它告诉我函数已重命名为生成警告的表单。

使某个内容可编码并不会自动使其成为属性列表对象。而且你的字典没有输入
字符串,这也是一项要求。它是可编码的吗?然后,保存编码的“数据”(无论是JSON还是其他)。这是一个允许保存到
UserDefaults
@Larme中的类型,但这几乎足够了,我仍然收到警告。我会更新我的更改,你能看一下吗?搜索这些错误,你会找到解决方案。我没有找到清晰一致的解决方案。。你有没有特别提到@rmaddy?当我搜索unarchive时,我找到了一个封装在try块中的解决方案,它不执行警告中所说的操作,这是最容易实现的答案。我没有找到明确的反向搜索结果(对其进行编码),使某些内容可编码不会自动使其成为属性列表对象。而且你的字典没有输入
字符串,这也是一项要求。它是可编码的吗?然后,保存编码的“数据”(无论是JSON还是其他)。这是一个允许保存到
UserDefaults
@Larme中的类型,但这几乎足够了,我仍然收到警告。我会更新我的更改,你能看一下吗?搜索这些错误,你会找到解决方案。我没有找到清晰一致的解决方案。。你有没有特别提到@rmaddy?当我搜索unarchive时,我找到了一个封装在try块中的解决方案,它不执行警告中所说的操作,这是最容易实现的答案。我找不到明确的反向顶部搜索结果(对其进行编码)