2017-03-13 2 views
1

PurposeEncode verschachtelt Aufzählung swift 3

Ich habe eine User-Klasse mit einem Status Eigentum und ich möchte speichere es in NSUserDefault, die die User-Klasse zuerst codieren müssen.

Benutzerklassencode aktualisierte Version

public class User: NSObject, NSCoding { 

    override init() {} 

    var status: Status = .unKnow 

    required convenience public init(coder aDecoder: NSCoder) { 

     self.init() 

     self.status = aDecoder.decodeObject(forKey: "UserStatus") as? Status ?? .unKnow 

    } 

    public func encode(with aCoder: NSCoder) { 

     aCoder.encode(self.status, forKey: "UserStatus") 
    } 

    public func updatePersistentData() { 

     let userDefault = UserDefaults.standard 
     /// stuck at this line 
     let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: self) 

     userDefault.set(encodedData, forKey: "User") 
     userDefault.synchronize() 

    } 
} 

Und meine verschachtelte Aufzählung

enum Status { 
    /// is Login status 
    case isLogin(style: LoginStatus) 
    /// is register 
    case isRegister(style: RegisterStatus) 
    /// is fetch user info 
    case isGetUserInfo(style: GetUserInfoStatus) 
    /// nonabove 
    case unKnow 
} 

enum LoginStatus: Int { 
    case a 
    case b 
    case c 
    case d 
} 

enum RegisterStatus: Int { 
    case a 
    case b 
    case c 
    case d 
} 

enum GetUserInfoStatus: Int { 
    case a 
    case b 
    case c 
    case d 
} 

Ich fand this und verstehe ich Enum in Rohwert konvertieren müssen. Es scheint notwendig, eine normale Enum mit String-Stil oder Int-Style zu verwenden.

Und ich führen Sie den Code, Fehlermeldung

HJC[2371:403228] -[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x7f940e6bec30 
HJC[2371:403228] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x7f940e6bec30' 

Antwort

2

Ich habe versucht, den Status zu kodieren und dekodieren, da es die einzige Eigenschaft in der Klasse ist, aber Sie könnten das gleiche für die anderen Eigenschaften tun müssen, falls vorhanden war gefunden

Zuerst begann ich die State enum ein Wert mit Angabe, dass ich

enum Status { 

    enum StatusValue { 
     case isLogin(LoginStatus) 
     case isRegister(RegisterStatus) 
     case isGetUserInfo(RegisterStatus) 
     case unknow 
    } 
} 

extension Status.StatusValue { 

    var value: Int { 
     switch self { 
     case .isLogin(let value): 
     return value.rawValue 
     case .isRegister(let value): 
     return value.rawValue 
     case .isGetUserInfo(let value): 
     return value.rawValue 
     case .unknow: 
     return -1 
     } 

    } 
} 

enum LoginStatus: Int { 
    case a = 0 
    case b 
    case c 
    case d 
} 

enum RegisterStatus: Int { 
    case a = 4 
    case b 
    case c 
    case d 
} 

enum GetUserInfoStatus: Int { 
    case a = 8 
    case b 
    case c 
    case d 
} 

Zweitens kodieren kann so konfiguriert ich die.210 Klasse NSCoding

public class User: NSObject, NSCoding { 

    override init() { 
     status = .unknow 
    } 

    init(_ status: Status.StatusValue) { 
     self.status = status 
    } 

    var status: Status.StatusValue 

    public func encode(with aCoder: NSCoder) { 
     print(self.status.value) 
     aCoder.encode(self.status.value, forKey: "status") 
    } 

    public required convenience init(coder aDecoder: NSCoder) { 
     let status = aDecoder.decodeObject(forKey: "status") as? Status.StatusValue ?? .unknow 

     self.init(status) 
    } 

    func save() { 
     let savedData = NSKeyedArchiver.archivedData(withRootObject: self) 
     let defaults = UserDefaults.standard 
     defaults.set(savedData, forKey: "user") 
     defaults.synchronize() 
    } 
} 

Schließlich zu implementieren ich das Ergebnis durch

let user1: User = User() 
user1.status = .isLogin(LoginStatus.b) 
user1.save() 

let user2: User 

let defaults = UserDefaults.standard 

if let saveduser = defaults.object(forKey: "user") as? Data { 
    user2 = NSKeyedUnarchiver.unarchiveObject(with: saveduser) as! User 
    print(user2) 
} 

getestet würde ich vorschlagen, auch ein wenig darüber hier zu lesen: NSCoding, Workaround for Swift Enum with raw type + case arguments?

+0

Vielen Dank für die Antwort, aber Ich habe immer noch den Fehler 'Beenden der App aufgrund der nicht abgefangenen Ausnahme 'NSInvalidArgumentException', Grund: '- [_ SwiftValue encodeWithCoder:]: unerkannter Selektor an Instanz 0x7f940e6bec30 gesendet'' in dieser Methode ** lese codedData: Data = NSKeyedArch iver.archivedData (withRootObject: self) ** was in der User-Klasse geschrieben wird –

+1

@StephenChen Ich bemerkte von Ihrem Fehler, dass Sie 'func encodeWithCoder (aCoder: NSCoder)' anstelle von 'public func encode (mit aCoder: NSCoder) verwenden '. Ist das der Fall oder ist das ein neuer Fehler, den Sie vorher nicht bekommen haben? – Prientus

+0

@Prientus Entschuldigung, ich hatte falsch tippen. Vielen Dank für die Nachricht, in meinem Code habe ich 'Public Func encode (mit aCoder: NSCoder)' –