Attempt to Insert Non-Property List Object When Trying to Save a Custom Object in Swift 3

Attempt to insert non-property list object when trying to save a custom object in Swift 3

You need to create Data instance from your JobCategory model using JSONEncoder and store that Data instance in UserDefaults and later decode using JSONDecoder.

struct JobCategory: Codable {
let id: Int
let name: String
}

// To store in UserDefaults
if let encoded = try? JSONEncoder().encode(category) {
UserDefaults.standard.set(encoded, forKey: UserDefaultsKeys.jobCategory.rawValue)
}

// Retrieve from UserDefaults
if let data = UserDefaults.standard.object(forKey: UserDefaultsKeys.jobCategory.rawValue) as? Data,
let category = try? JSONDecoder().decode(JobCategory.self, from: data) {
print(category.name)
}

Old Answer

You need to create Data instance from your JobCategory instance using archivedData(withRootObject:) and store that Data instance in UserDefaults and later unarchive using unarchiveTopLevelObjectWithData(_:), So try like this.

For Storing data in UserDefaults

let category = JobCategory(id: 1, name: "Test Category", URLString: "http://www.example-job.com")
let encodedData = NSKeyedArchiver.archivedData(withRootObject: category, requiringSecureCoding: false)
let userDefaults = UserDefaults.standard
userDefaults.set(encodedData, forKey: UserDefaultsKeys.jobCategory.rawValue)

For retrieving data from UserDefaults

let decoded  = UserDefaults.standard.object(forKey: UserDefaultsKeys.jobCategory.rawValue) as! Data
let decodedTeams = NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decoded) as! JobCategory
print(decodedTeams.name)

Cannot set non-property-list object in UserDefaults

The answer was to use keyedArchiver to convert the object to an NSData object. Here is the Swift 3 code for storing, and retrieving the object:

func saveGame() {
UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: hero), forKey: HeroObjectKey)
}

func defaultExistsForGameData() -> Bool {

var gameData = false

if let heroObject = UserDefaults.standard.value(forKey: HeroObjectKey) as? NSData {
hero = NSKeyedUnarchiver.unarchiveObject(with: heroObject as Data) as! Hero
gameData = true
}

return gameData
}

Userdefault error with Attempt to set a non-property-list object

Please read the error message carefully, it's pretty clear.

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object ( "(temperature: \"C\", measurement: \"mm\")" ) for key Current Weather Setting'

The list object is a tuple which is not property list compliant.

A reasonable solution is a custom struct and Codable, the completion handler is pointless because UserDefaults is synchronous.

struct WeatherUnit : Codable {
let temperature, measurement : String
}

var currentWeatherUnit = [WeatherUnit]()

func checkingForSetting() {
if let data = UserDefaults.standard.data(forKey: "Current Weather Setting") {
do {
currentWeatherUnit = try PropertyListDecoder().decode([WeatherUnit].self, from: data)
print("Current weather setting is exist")
} catch { print(error) }
} else {
currentWeatherUnit = [WeatherUnit(temperature: "C", measurement: "mm")]
let data = try? PropertyListEncoder().encode(currentWeatherUnit)
UserDefaults.standard.set(data, forKey: "Current Weather Setting")
print("Create new setting for current weather")
}
}

Attempt to insert non-property list object error while storing dictionary in userdefaults

User defaults is a property list. Property list dictionaries must have string keys.

You can always test the eligibility of something to be put directly into User Defaults like this:

let d : [Int:[Int]] = [1100110004 : [1,2,0,0]]
do {
let data = try PropertyListSerialization.data(
fromPropertyList: d, format: .binary, options: 0)
} catch { print(error) }

A simple and obvious solution: your d is Codable, so encode it to a property list and store the resulting Data object in user defaults.

let d : [Int:[Int]] = [1100110004 : [1,2,0,0]]
do {
let data = try PropertyListEncoder().encode(d)
// and store `data` in user defaults
} catch { print(error) }

Attempt to set a non-property-list object as an NSUserDefaults

The code you posted tries to save an array of custom objects to NSUserDefaults. You can't do that. Implementing the NSCoding methods doesn't help. You can only store things like NSArray, NSDictionary, NSString, NSData, NSNumber, and NSDate in NSUserDefaults.

You need to convert the object to NSData (like you have in some of the code) and store that NSData in NSUserDefaults. You can even store an NSArray of NSData if you need to.

When you read back the array you need to unarchive the NSData to get back your BC_Person objects.

Perhaps you want this:

- (void)savePersonArrayData:(BC_Person *)personObject {
[mutableDataArray addObject:personObject];

NSMutableArray *archiveArray = [NSMutableArray arrayWithCapacity:mutableDataArray.count];
for (BC_Person *personObject in mutableDataArray) {
NSData *personEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:personObject];
[archiveArray addObject:personEncodedObject];
}

NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
[userData setObject:archiveArray forKey:@"personDataArray"];
}


Related Topics



Leave a reply



Submit