Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save custom objects into NSUserDefaults [duplicate]

I'm having a news ViewController and a TeamViewController. The TeamViewController contain a tableView of teamObjects which when selected is added into array. I want to add this array into NSUserDefaults so i can access them from the NewsController which contain a url request where the teamObjects is needed. However i keep getting:

'Attempt to insert non-property list object ( "" ) for key teams'

I'm open for other suggestions if there is better ways than storing it in NSUserDefaults

didSelectRowAtIndexPath method

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {     tableView.deselectRowAtIndexPath(indexPath, animated: true)       let team = self.teamArray[indexPath.row] as Team     var removed = false      for (index, value) in enumerate(self.teamSelected) {         if (value == team) {             self.teamSelected.removeAtIndex(index)             removed = true         }     }      if (!removed) {         self.teamSelected.append(team)     }      var userDefaults = NSUserDefaults.standardUserDefaults()     userDefaults.setValue(self.teamSelected, forKey: "teams")     userDefaults.synchronize()      tableView.reloadData() } 

My object

class Team: NSObject{     var id: Int!     var name: NSString!     var shortname: NSString!       init(id: Int, name:NSString, shortname: NSString) {         self.id = id         self.name = name         self.shortname = shortname      }  } 
like image 801
Peter Pik Avatar asked May 01 '15 12:05

Peter Pik


People also ask

How do you save an array of objects in UserDefaults?

Let's take a look at an example. We access the shared defaults object through the standard class property of the UserDefaults class. We then create an array of strings and store the array in the user's defaults database by invoking the set(_:forKey:) method of the UserDefaults database.

How much data can you store in NSUserDefaults?

It appears the limit is the maximum file size for iOS (logically), which is currently 4GB: https://discussions.apple.com/thread/1763096?tstart=0. The precise size of the data is circumscribed by the compiler types (NSData, NSString, etc.) or the files in your asset bundle.

What types can you store natively in NSUserDefaults?

Storing Default Objects The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Boolean values, and URLs.


2 Answers

Actually, you will need to archive the custom object into NSData then save it to user defaults and retrieve it from user defaults and unarchive it again. You can archive it like this

let teams = [Team(id: 1, name: "team1", shortname: "t1"), Team(id: 2, name: "team2", shortname: "t2")]  var userDefaults = UserDefaults.standard let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: teams) userDefaults.set(encodedData, forKey: "teams") userDefaults.synchronize() 

and unarchive it like this

let decoded  = userDefaults.data(forKey: "teams") let decodedTeams = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Team] 

But if you just did that you will get

.Team encodeWithCoder:]: unrecognized selector sent to instance 

You will have to make Team conform to NSCoding just like this

class Team: NSObject, NSCoding {     var id: Int     var name: String     var shortname: String       init(id: Int, name: String, shortname: String) {         self.id = id         self.name = name         self.shortname = shortname      }      required convenience init(coder aDecoder: NSCoder) {         let id = aDecoder.decodeInteger(forKey: "id")         let name = aDecoder.decodeObject(forKey: "name") as! String         let shortname = aDecoder.decodeObject(forKey: "shortname") as! String         self.init(id: id, name: name, shortname: shortname)     }      func encode(with aCoder: NSCoder) {         aCoder.encode(id, forKey: "id")         aCoder.encode(name, forKey: "name")         aCoder.encode(shortname, forKey: "shortname")     } } 
like image 195
mohamede1945 Avatar answered Sep 24 '22 14:09

mohamede1945


You can try NSKeyedUnarchiver, like below

Here i stored UIColor Object in UserDefault You can change it with your object

 NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:color]; [[NSUserDefaults standardUserDefaults] setObject:colorData forKey:@"myColor"]; 

and to retrive that

NSData *colorData = [[NSUserDefaults standardUserDefaults] objectForKey:@"myColor"]; UIColor *color = [NSKeyedUnarchiver unarchiveObjectWithData:colorData]; 

Note : This is Objective C but I hope you can covert this in Swift

Hope this solve your problem


Update : Swift 5

Archive in Swift

do{     let colorAsData = try NSKeyedArchiver.archivedData(withRootObject: UIColor.red, requiringSecureCoding: true)     UserDefaults.standard.set(colorAsData, forKey: "myColor")     UserDefaults.standard.synchronize() }catch (let error){      #if DEBUG         print("Failed to convert UIColor to Data : \(error.localizedDescription)")     #endif } 

Unarchive in Swift

do{     if let colorAsData = UserDefaults.standard.object(forKey: "myColor") as? Data{         if let color = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [UIColor.self], from: colorAsData){             // Use Color         }     } }catch (let error){     #if DEBUG         print("Failed to convert UIColor to Data : \(error.localizedDescription)")     #endif } 
like image 37
Malav Soni Avatar answered Sep 22 '22 14:09

Malav Soni