2014-10-12 13 views
53

HintergrundWie kodiere ich enum mit NSCoder in swift?

Ich versuche, einen String-Stil Enum mit dem NSCoding Protokoll zu codieren, aber ich laufe in Fehler zu konvertieren und zurück von String.

ich die folgenden Fehler während Decodierung und Codierung:

String ist nicht konvertierbar

zusätzliches Argument forKey auf der Bühne: in Call

-Code

enum Stage : String 
    { 
     case DisplayAll = "Display All" 
     case HideQuarter = "Hide Quarter" 
     case HideHalf  = "Hide Half" 
     case HideTwoThirds = "Hide Two Thirds" 
     case HideAll  = "Hide All" 
    } 

    class AppState : NSCoding, NSObject 
    { 
     var idx = 0 
     var stage = Stage.DisplayAll 

     override init() {} 

     required init(coder aDecoder: NSCoder) { 
      self.idx = aDecoder.decodeIntegerForKey("idx" ) 
      self.stage = aDecoder.decodeObjectForKey( "stage") as String // ERROR 
     } 

     func encodeWithCoder(aCoder: NSCoder) { 
      aCoder.encodeInteger(self.idx,    forKey:"idx" ) 
      aCoder.encodeObject( self.stage as String, forKey:"stage") // ERROR 
     } 

    // ... 

    } 

Antwort

57

Sie müssen die Enumeration in und von dem Rohwert konvertieren.

class AppState : NSObject, NSCoding 
{ 
    var idx = 0 
    var stage = Stage.DisplayAll 

    override init() {} 

    required init(coder aDecoder: NSCoder) { 
     self.idx = aDecoder.decodeIntegerForKey("idx") 
     self.stage = Stage(rawValue: (aDecoder.decodeObjectForKey("stage") as! String)) ?? .DisplayAll 
    } 

    func encodeWithCoder(aCoder: NSCoder) { 
     aCoder.encodeInteger(self.idx, forKey:"idx") 
     aCoder.encodeObject( self.stage.rawValue, forKey:"stage") 
    } 

    // ... 

} 

Swift 1.1 (Xcode 6.1), verwendet as statt as!: In Swift 1.2 (Xcode 6.3), dies würde wie folgt aussehen

self.stage = Stage(rawValue: (aDecoder.decodeObjectForKey("stage") as String)) ?? .DisplayAll 

Swift 1.0 (Xcode 6.0) verwendet toRaw() und fromRaw() wie folgt aus:

self.stage = Stage.fromRaw(aDecoder.decodeObjectForKey("stage") as String) ?? .DisplayAll 

    aCoder.encodeObject(self.stage.toRaw(), forKey:"stage") 
+0

Wenn Sie wie! dann kann der String nie nil sein und '?? .DisplayAll' ist nutzlos. Sollte es nicht "wie" sein? – Oren

+2

Das 'as!' Erzeugt den 'String', der existiert, damit der Cast erfolgreich ist. 'Stage (rawValue:" someString ")' gibt ein optionales Argument zurück, da die Zeichenfolge möglicherweise keinen gültigen Enum-Wert definiert. Sie müssen das optional auspacken. Der Operator * nil coalescing * ersetzt dieses optionale Element durch eine nicht ausgepackte Version, falls es existiert, oder durch ein ".DisplayAll", falls dies nicht der Fall ist. – vacawama

9

Update für Xcode 6.3, Swift 1.2:

self.stage = Stage(rawValue: aDecoder.decodeObjectForKey("stage") as! String) ?? .DisplayAll 

Note die as!