1

I am not clear why I cannot save this to userprefs with:

/** 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)
}

The NotificationSpecification object I am saving is:

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

internal var backgroundNotifications: [Date:[App:NotificationSpecification]] // this one does not save.

my app struct is:

struct App: Hashable, Codable, Equatable {
    let name: String
    let notify: String
    let id: String
    let isSubscribed: Bool
}

and the notificationspecification is:

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
    }
}

The error that I am receiving is:

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'

is it because of custom_headers? what can I do about it -- do I have to manually transform it to/from json?

edit

Following Larme's suggestion:

/** 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
}

I am getting:

'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead

and

'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead

If I change it to NSKeyedArchiver.archivedDataWithRootObject( backgroundNotification)

it tells me that the function has been renamed to the form that is generating the warning.

Bhavesh Nayi
  • 3,626
  • 1
  • 27
  • 42
roberto tomás
  • 4,435
  • 5
  • 42
  • 71
  • Making something Codable doesn't automatically make it a property list object. And your dictionary isn't keyed with `String` which is also a requirement. – rmaddy Apr 27 '19 at 17:14
  • 1
    It's Codable? Then, save the "Data" encoded (wether it's JSON or another one). That's one a the allowed type to be saved into `UserDefaults`. – Larme Apr 27 '19 at 17:15
  • @Larme this was _almost enough_ I am still getting warnigns though. I'll update with my changes, can you take a look please? – roberto tomás Apr 27 '19 at 17:24
  • Search on those errors and you will find the solution. – rmaddy Apr 27 '19 at 17:34
  • Im not finding clear and consistent solutions .. Did you have a specific reference in mind @rmaddy? When I search the unarchive, I find a solution that wraps in a try block and does not do what the warning says to do, as the top clearly implementable answer. I find no clear top search result for the inverse (encoding it) – roberto tomás Apr 27 '19 at 17:37
  • example of a solution to unarchive that expressly avoids solving the first problem: https://stackoverflow.com/questions/51487622/unarchive-array-with-nskeyedunarchiver-unarchivedobjectofclassfrom – roberto tomás Apr 27 '19 at 17:41
  • actually if I search more specifically for the remaining unanswered question google says: No results found for "'archivedData(withRootObject:)' was deprecated in iOS 12.0". -- I do see that it is [flagged as depreciated](https://developer.apple.com/documentation/foundation/nskeyedarchiver/1413189-archiveddata) in the apple documentation, but they never link to any strategy to remove depreciations in their documentation. – roberto tomás Apr 27 '19 at 18:01
  • I ended up going with JSONEncoder and JSONDecoder since there is no known solution with `archivedData` – roberto tomás Apr 27 '19 at 18:32

0 Answers0