Save an object in NSUserDefaults and Realm
Using Swift4's Codable
protocol, you can save a custom class to UserDefaults
without having to conform to the old NSCoding
protocol.
class Team: Object, Codable {
@objc dynamic var id:Int = 0
@objc dynamic var name:String = ""
}
let team = Team()
team.id = 1
team.name = "Team"
let encodedTeam = try! JSONEncoder().encode(team)
UserDefaults.standard.set(encodedTeam, forKey: "team")
let decodedTeam = try! JSONDecoder().decode(Team.self, from: UserDefaults.standard.data(forKey: "team")!)
This solves the problem of multiple inheritance, since your type doesn't need to inherit from NSObject
anymore.
How to save an array of objects to NSUserDefault with swift?
From the Property List Programming Guide:
If a property-list object is a container (that is, an array or dictionary), all objects contained within it must also be property-list objects. If an array or dictionary contains objects that are not property-list objects, then you cannot save and restore the hierarchy of data using the various property-list methods and functions.
You'll need to convert the object to and from an NSData
instance using NSKeyedArchiver
and NSKeyedUnarchiver
.
For example:
func savePlaces(){
let placesArray = [Place(lat: 123, lng: 123, name: "hi")]
let placesData = NSKeyedArchiver.archivedDataWithRootObject(placesArray)
NSUserDefaults.standardUserDefaults().setObject(placesData, forKey: "places")
}
func loadPlaces(){
let placesData = NSUserDefaults.standardUserDefaults().objectForKey("places") as? NSData
if let placesData = placesData {
let placesArray = NSKeyedUnarchiver.unarchiveObjectWithData(placesData) as? [Place]
if let placesArray = placesArray {
// do something…
}
}
}
Is it possible to save an NSManagedObject in NSUserDefaults?
No, you should not store an NSManagedObject
in NSUserDefaults
. Core Data is an object persistence technology, so it doesn't make sense to try and persist an NSManagedObject
in some other format.
There are few alternatives you can use:
- You could simply store the name of the lift in your user defaults and then query for this to get the object back from Core Data. This may not work for you if lift names aren't unique
- You can add an identifier attribute to your Lift entity and store something like a UUID string in that attribute; You can then store the same string in UserDefaults. This will ensure one object is selected uniquely.
- You can add a new boolean attribute to your Lift entity
default
and again use a query to retrieve it; You would need to ensure you only set the value to true on one lift at a time. - You can use
managedObject.objectId.uriRepresentation
to get a URL that you can store as a string and then use to retrieve the object later. This is probably the most complex solution and I would suggest you try one of the other options.
iOS Swift Storing Realm Object to UserDefaults.standard
You'll need to supply conformance methods to NSCoding
for your Realm models in order to be able to persist them to UserDefaults
.
However, I'd encourage you to use Realm to persist Realm models given that you're already using Realm in your app.
Can I use Realm for all data storage, or should I use NSUserDefaults for storing username/password?
You should not store passwords or any sensitive information inside NSUserDefault
, by using a simple file manager you can read all the data stored in it, it is really unsafe.
you don't even need a database or sort of. The right place to store sensitive info is the keychain of your device.
There are a lot of libs on github that can help you in using it.
Pay attention that what you save inside the keychain will persist even after you remove the application.
Trying to save custom object in UserDefaults using NSKeyedArchiver
Use JSONEncoder to save data to UserDefaults. Dummy code:
class YourClassName: Codable {
//Your properties here
func saveInPreference() {
do {
let jsonEncoder = JSONEncoder()
UserDefaults.standard.set(try jsonEncoder.encode(Your object here), forKey: "Write UserDefaultKey here")
UserDefaults.standard.synchronize()
}
catch {
print(error.localizedDescription)
}
}
}
Hope that helps!
@Faraz A. Khan comment if you have any questions in the above piece of code.
Save Dictionary into NSUserDefaults Swift
I managed to save my custom Dictionary using Realm!
Instead of a struct I use a different class like this:
import RealmSwift
class Sensors : Object {
dynamic var sensorName = ""
dynamic var sensorType = ""
dynamic var sensorSub = ""
}
and then I fill it like this:
var useOfRealm = try! Realm()
var allSensors = useOfRealm.objects(Sensors.self)
var saving = Sensors()
func fillThis() {
try! useOfRealm.write {
saving.sensorName = "something"
saving.sensorType = "something"
saving.sensorSub = "something"
useOfRealm.add(saving)
}
}
Use the function with parameters so you can fill the 'Dictionary' Dynamically.
Use allSensors
so you can retrieve everything that you want.
Swift saving and retrieving custom object from UserDefaults
Swift 4 or later
You can once again save/test your values in a Playground
UserDefaults need to be tested in a real project. Note: No need to force synchronize. If you want to test the coding/decoding in a playground you can save the data to a plist file in the document directory using the keyed archiver. You need also to fix some issues in your class:
class Person: NSObject, NSCoding {
let name: String
let age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
required init(coder decoder: NSCoder) {
self.name = decoder.decodeObject(forKey: "name") as? String ?? ""
self.age = decoder.decodeInteger(forKey: "age")
}
func encode(with coder: NSCoder) {
coder.encode(name, forKey: "name")
coder.encode(age, forKey: "age")
}
}
Testing:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
do {
// setting a value for a key
let newPerson = Person(name: "Joe", age: 10)
var people = [Person]()
people.append(newPerson)
let encodedData = try NSKeyedArchiver.archivedData(withRootObject: people, requiringSecureCoding: false)
UserDefaults.standard.set(encodedData, forKey: "people")
// retrieving a value for a key
if let data = UserDefaults.standard.data(forKey: "people"),
let myPeopleList = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [Person] {
myPeopleList.forEach({print($0.name, $0.age)}) // Joe 10
}
} catch {
print(error)
}
}
}
Related Topics
No Such File and Directory Found Xcode 7
How to Draw a Smooth Circle with Cashapelayer and Uibezierpath
How to Pop Two Views at Once from a Navigation Controller
Disable Scroll on a Uiwebview Allowed
Icon Already Includes Gloss Effects
New React Native Project with Old Version of React Native
Linker Error in Xcode 5 for Libzbar.A
Objective-C Delay Action with Blocks
Avaudiosession Setcategory Swift 4.2 iOS 12 - Play Sound on Silent
Return Lighter Color from Skcolor Using Hsl Lightness Factor
Alamofire:How to Handle Errors Globally
How to Change Height of Grouped Uitableview Header
How to Remove All Navigationbar Back Button Title
How to Solve "Error Running Pod Install" in Flutter on MAC