NSCoder et les enums Swift

Joanna CarterJoanna Carter Membre, Modérateur

Je viens de jouer avec le restorableState d'un UIViewController et je voulais sauvegarder un enum Swift.


 


"C'est pas possible" je vous entends crier.


 


Mais si !



extension NSCoder
{
func encode<EnumType: RawRepresentable>(_ enumValue: EnumType, forKey key: String)
{
encode(enumValue.rawValue, forKey:key)
}

func decodeEnum<EnumType : RawRepresentable>(forKey key: String) -> EnumType?
{
if let rawValue = decodeObject(forKey: key) as? EnumType.RawValue
{
return EnumType.init(rawValue: rawValue)
}

return nil
}
}

Et pour l'utiliser :



enum Index : Int
{
case zero = 0
case une
case deux
}


class ViewController : UIViewController
{
var index: Index = zero

override func encodeRestorableState(with coder: NSCoder)
{
super.encodeRestorableState(with: coder)

coder.encode(self.index, forKey: "Index")
}

override func decodeRestorableState(with coder: NSCoder)
{
super.decodeRestorableState(with: coder)

guard let index = coder.decodeEnum(forKey: "Index") as Index? else
{
return
}

...
}
}

Réponses

  • NSCoding est super pour sauvegarder des données, mais à  partir d'une classe dont c'est le rôle. Perso, je fais dériver cette classe directement de NSObject. Ensuite, tu peux updater autant que tu veux, et pour peu que tu aies donné des valeurs par défaut à  ta classe, tu peux ajouter des nouvelles valeurs à  tes anciennes archives sans problème. De ce fait, le fonctionnement en arborescence de NSCoding surclasse totalement la sérialisation. Pourquoi donc veux-tu régresser vers la sérialisation? (le terme n'est pas trop fort me semble t-il...)


     


    Logiquement, tu devrais avoir une classe indépendante de ta UIViewController dont le travail est, justement de "NSKeyArchiver" des "NSCodées" valeurs ou instances de classe, ou tout ce que tu veux (sans oublier les NSCodées de classes NSCodées de classes...)


  • Joanna CarterJoanna Carter Membre, Modérateur
    septembre 2016 modifié #3

    C'est pas une question de sauvegarder l'état de n'importe quel objet. Ce que je fais, c'est une partie du mécanisme de State Preservation d'un ViewController (https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/PreservingandRestoringState.html).


     


    Les deux méthodes : encodeRestorableState et decodeRestorableState, sont invoqués par le système chaque fois que l'app soit mis en arrière-plan et réveillé. Du coup, l'utilisateur trouvera l'app dans le même état où il l'a quitté, au lieu de le recommencer.


     


    J'aurais pu sauvegarder le rawValue de l'enum mais j'ai voulu déterminer s'il serait possible de sauvegarder les enums et, voilà , c'est bien possible, si on utilise l'extension de NSCoder que j'ai rédigé.


  • D'une manière comme d'une autre il est grand temps qu'ils permettent le bridging entre Swift et Objective-C. Mais il va falloir attendre Swift 4...


     


    Un peu de lecture sur le sujet


  • Joanna CarterJoanna Carter Membre, Modérateur
    septembre 2016 modifié #5


    D'une manière comme d'une autre il est grand temps qu'ils permettent le bridging entre Swift et Objective-C. Mais il va falloir attendre Swift 4...




     


    Je suis d'accord et j'ai déjà  fait des expériences avec le protocole _ObjectiveCBridgeable. ça marche très bien mais ils ont décidé de le laisser privé, bien qu'il est accessible.


     


    Mais dans le cas d'un enum, c'est assez compliqué de faire une classe Objective-C qui pourrait représenter les enums sophistiqué que l'on trouve en Swift.




  • Mais dans le cas d'un enum, c'est assez compliqué de faire une classe Objective-C qui pourrait représenter les enums sophistiqué que l'on trouve en Swift.




    NSData. J'avais fait des tests et tu pouvais passer un enum en dumpant directement dans la mémoire avec des pointeurs mais ça remonte...


    Et _ObjectiveCBridgeable n'est pas fonctionnel. J'ai testé dans CoreGeometry ça marche pas.

Connectez-vous ou Inscrivez-vous pour répondre.