Comment archiver et désarchiver des objets personnalisés dans Swift? Ou comment économiser de l'objet personnalisé à NSUserDefaults dans Swift?
J'ai une classe
class Player {
var name = ""
func encodeWithCoder(encoder: NSCoder) {
encoder.encodeObject(name)
}
func initWithCoder(decoder: NSCoder) -> Player {
self.name = decoder.decodeObjectForKey("name") as String
return self
}
init(coder aDecoder: NSCoder!) {
self.name = aDecoder.decodeObjectForKey("name") as String
}
init(name: String) {
self.name = name
}
}
et je veux serialise et de l'enregistrer à l'utilisateur par défaut.
Tout d'abord, je ne suis pas sûr de la façon d'écrire correctement le codeur et le décodeur. Donc, pour l'init, j'ai écrit deux méthodes.
Lorsque j'essaie d'exécuter ce code:
func saveUserData() {
let player1 = Player(name: "player1")
let myEncodedObject = NSKeyedArchiver.archivedDataWithRootObject(player1)
NSUserDefaults.standardUserDefaults().setObject(myEncodedObject, forKey: "player")
}
application se bloque et je reçois ce message:
*** NSForwarding: warning: object 0xebf0000 of class '_TtC6GameOn6Player' does not implement methodSignatureForSelector: -- trouble ahead
Que dois-je faire de mal?
- Juste pour envoyer un buzz, récemment, j'ai fait un post sur Swift forum de répondre à une question similaire, j'espère que ça aide. devforums.apple.com/message/1044432#1044432
- cela fonctionne parfaitement :).
Vous devez vous connecter pour publier un commentaire.
NSKeyedArchiver
ne fonctionne qu'avec Objective-C classes, pas de pure Swift classes. Vous pouvez réduire votre classe Objective-C par marquage avec le@objc
attribut ou en héritant de l'Objective-C classe commeNSObject
.Voir L'utilisation de Swift avec Cocoa et Objective-C pour plus d'informations.
testé avec XCode 7.1.1, Swift 2.1 & iOS 9
Vous avez un peu d'options pour enregistrer votre (tableau de) objets personnalisés :
Je laisse de données de Base de cette discussion, mais veux vous montrer pourquoi il est mieux d'utiliser NSKeyedArchiver sur NSUserdefaults.
J'ai mis à jour votre Lecteur de classe et les méthodes fournies pour les deux options. Bien que les deux options de travail, si vous comparez le "load & enregistrer" méthodes vous verrez que NSKeydArchiver nécessite moins de code pour gérer les tableaux d'objets personnalisés. Aussi avec NSKeyedArchiver vous pouvez facilement stocker des choses dans des fichiers séparés, plutôt que d'avoir à vous soucier unique " clé " des noms pour chaque propriété.
J'ai testé cette classe comme suit (vue unique de l'application, dans la méthode viewDidLoad de la ViewController)
comme dit ci-dessus, les deux méthodes produisent le même résultat
Aussi dans la vie réelle demande que vous pourriez faire une meilleure gestion des erreurs dans le, archivage, & désarchivage pourrait échouer.
Dans Swift 4 vous n'avez pas besoin NSCoding plus! Il y a un nouveau protocole appelé
Codable
!Et
Codable
prend également en charge les Énumérations et les Structures de sorte que vous pouvez réécrire votre catégorie de joueur à un struct si vous voulez!Pour enregistrer votre lecteur dans Userdefaults:
Remarque: PropertyListEncoder() est une classe du framework Foundation
À Récupérer:
Pour plus d'informations, lire https://developer.apple.com/documentation/swift/codable
Dans Swift 4 /iOS 11, il y a une toute nouvelle façon de faire. Il a l'avantage d' tout Swift objet peut l'utiliser — et pas seulement les classes, mais aussi les structures et les énumérations.
Vous remarquerez que j'ai omis votre NSCoding méthodes liées, parce que vous n'aurez pas besoin d'eux pour ce but. Vous peut adopter NSCoding ici, comme vous le savez, mais vous n'avez pas à. (Et une structure ou enum ne peut pas adopter NSCoding à tous.)
Vous commencez par déclarer votre classe à l'adoption de la Codable protocole:
Il devient alors une simple question de sérialiser un objet de Données (NSData) qui peut être stocké dans UserDefaults. La très plus simple est d'utiliser une liste de propriétés en tant qu'intermédiaire:
Si vous utilisez cette approche, nous allons maintenant prouver que vous pouvez tirer le même Joueur de retour de UserDefaults:
Si vous préférez passer par un NSKeyedArchiver /NSKeyedUnarchiver, vous pouvez le faire à la place. En effet, il y a certains situations où vous aurez à faire: vous serez présenté avec un NSCoder, et vous aurez besoin d'encoder vos Codable objet à l'intérieur d'elle. Dans une récente bêta de Xcode 9 introduit une façon de le faire aussi. Par exemple, si vous êtes d'encodage, vous lancez la NSCoder vers le bas pour un NSKeyedArchiver et appel
encodeEncodable
.NSKeyedArchiver.setClassName("MyObject", for: MyObject.self)
puislet messageData = try? JSONEncoder().encode(myObject)
. Est-il un moyen d'éliminer l'utilisation de NSKeyed?Avec codable nouvel ios 11 protocole, vous pouvez maintenant laisser votre classe implémente et archiver/désarchiver des objets avec JSONEncoder et JSONDecoder