J'ai une classe personnalisée que je souhaite enregistrer dans NSUserDefaults
. On me dit que je dois convertir l'objet de classe en données afin de l'enregistrer dans NSUserDefaults
. J'ai trouvé beaucoup de chaînes ou d'entiers discrets dans les exemples de NSData
mais rien dans la classe personnalisée à NSData
. Je connais très peu les subtilités de l'encodage NSData
etc. Toute aide est appréciée
EDIT: Bien que je comprenne qu'il y a des réponses similaires ici, aucune d'entre elles n'est en Swift. La traduction entre les langues est faisable, mais elle est extrêmement fastidieuse et parfois très contre-intuitive.
Voici un exemple simple pour vous:
//Custom class.
class Person: NSObject, NSCoding {
var name: String!
var age: Int!
required convenience init(coder decoder: NSCoder) {
self.init()
self.name = decoder.decodeObjectForKey("name") as! String
self.age = decoder.decodeObjectForKey("age") as! Int
}
convenience init(name: String, age: Int) {
self.init()
self.name = name
self.age = age
}
func encodeWithCoder(coder: NSCoder) {
if let name = name { coder.encodeObject(name, forKey: "name") }
if let age = age { coder.encodeObject(age, forKey: "age") }
}
}
//create an instance of your custom class.
var newPerson = [Person]()
//add some values into custom class.
newPerson.append(Person(name: "Leo", age: 45))
newPerson.append(Person(name: "Dharmesh", age: 25))
//store you class object into NSUserDefaults.
let personData = NSKeyedArchiver.archivedDataWithRootObject(newPerson)
NSUserDefaults().setObject(personData, forKey: "personData")
//get your object from NSUserDefaults.
if let loadedData = NSUserDefaults().dataForKey("personData") {
if let loadedPerson = NSKeyedUnarchiver.unarchiveObjectWithData(loadedData) as? [Person] {
loadedPerson[0].name //"Leo"
loadedPerson[0].age //45
}
}
Testé avec aire de jeux.
J'espère que cela t'aides.
Cet exemple de code suivant est basé sur la réponse de Richie Rich (voir ci-dessus) et réussit les tests dans cet environnement:
Xcode version 9.1 (9B55)
Swift version 4.0.2 (swiftlang-900.0.69.2 clang-900.0.38, Target: x86_64-Apple-macosx10.9)
MacBook Air (11-inch, Mid 2012) with macOS High Sierra (version 10.13.1)
// Foundation is required to NSObject and NSCoding
import Foundation
// A custom class called Person with two properties (a string name and an
// integer age), that is a subclass of NSObject and adopts NSCoding protocol.
class Person: NSObject, NSCoding {
var name: String!
var age: Int!
// The convenience initializer for class Person
// Reference
// https://developer.Apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//Apple_ref/doc/uid/TP40014097-CH18-ID217
convenience init(name: String, age: Int) {
// self.init() is the designated initializer for class Person.
// Reference
// https://developer.Apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//Apple_ref/doc/uid/TP40014097-CH18-ID219
self.init()
self.name = name
self.age = age
}
// The initializer init(coder:) is required by NSCoding protocol
// Reference
// https://developer.Apple.com/documentation/foundation/nscoding
// https://developer.Apple.com/documentation/foundation/nscoding/1416145-init
required convenience init(coder aDecoder: NSCoder) {
self.init()
// as! is a type casting operator
// Reference
// https://developer.Apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//Apple_ref/doc/uid/TP40014097-CH32-ID388
self.name = aDecoder.decodeObject(forKey: "name") as! String
self.age = aDecoder.decodeInteger(forKey: "age")
}
// The instance method encode(with:) is required by NSCoding protocol
// Reference
// https://developer.Apple.com/documentation/foundation/nscoding
// https://developer.Apple.com/documentation/foundation/nscoding/1413933-encode
func encode(with anEncoder: NSCoder) {
if let name = name {
anEncoder.encode(name, forKey: "name")
}
if let age = age {
anEncoder.encode(age, forKey: "age")
}
}
}
// Create an array (or, generally speaking, a collection) as a container to
// hold instances of our custom class type Person.
// Reference
// https://developer.Apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html
var anArrayOfPersons = [Person]()
print(anArrayOfPersons.count) // 0
// Add two instances into anArrayOfPersons.
// Reference
// https://developer.Apple.com/documentation/Swift/array
// https://developer.Apple.com/documentation/Swift/array/1538872-append
anArrayOfPersons.append(Person(name: "Cong", age: 33))
anArrayOfPersons.append(Person(name: "Sunny", age: 2))
// Archive anArrayOfPersons into NSData using NSKeyedArchiver.
// Reference
// https://developer.Apple.com/documentation/foundation/nskeyedarchiver
// https://developer.Apple.com/documentation/foundation/nskeyedarchiver/1413189-archiveddata
let dataToSave = NSKeyedArchiver.archivedData(withRootObject: anArrayOfPersons)
// Persist data. Storing anArrayOfPersons into UserDefaults as data.
// Reference
// https://developer.Apple.com/documentation/foundation/userdefaults
// https://developer.Apple.com/documentation/foundation/userdefaults/1414067-set
UserDefaults().set(dataToSave, forKey: "tagOfData")
// Take our stored data (in previous step) from UserDefaults using the key
// "personData". Optional binding is used to make sure the retrieved data is
// not nil.
// Reference
// https://developer.Apple.com/documentation/foundation/userdefaults
// https://developer.Apple.com/documentation/foundation/userdefaults/1409590-data
// https://developer.Apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//Apple_ref/doc/uid/TP40014097-CH5-ID333
if let dataRetrieved = UserDefaults().data(forKey: "tagOfData"),
// Decode our instance objects from the retrieved data
// Reference
// https://developer.Apple.com/documentation/foundation/nskeyedunarchiver
// https://developer.Apple.com/documentation/foundation/nskeyedunarchiver/1413894-unarchiveobject
let anArrayOfPersonsRetrieved = NSKeyedUnarchiver.unarchiveObject(with: dataRetrieved) as? [Person] {
// See how many bytes the data we retrieved has.
print(dataRetrieved) // 393 bytes
// See if the name and age properties are the same as what we stored.
print(anArrayOfPersonsRetrieved[0].name) // "Cong"
print(anArrayOfPersonsRetrieved[0].age) // 45
print(anArrayOfPersonsRetrieved[1].name) // "Sunny"
print(anArrayOfPersonsRetrieved[1].age) // 2
}
Ce lien peut vous aider
Il est important que votre classe étende NSObject
et NSCoding
, car la conversion doit être sa classe, NSCoding
est une interface pour sérialiser et désérialiser votre classe
Enregistrement personnalisé Swift avec NSCoding vers UserDefaults