编码嵌套枚举 swift 3

Encode nested enumeration swift 3

目的

我有一个用户 class,其状态为 属性,我想将其存储到需要对用户 class 进行编码的 NSUserDefault 中第一.

用户class代码更新版本

 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()

   }
}

还有我的嵌套枚举

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
}

我找到了 this,并且知道我需要将枚举转换为原始值。似乎需要使用具有字符串样式或 Int 样式的普通枚举...等

而我运行代码,错误信息

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'

我尝试对状态进行编码和解码,因为它是 class 中唯一的 属性,但如果找到任何其他属性,您可能需要对其他属性执行相同的操作

首先我开始给 State 枚举一个我可以编码的值

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
}

其次,我配置了 User class 来实现 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()
   }
}

最后我通过

测试了结果
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)
}

我还建议在这里阅读一些相关内容:NSCoding, Workaround for Swift Enum with raw type + case arguments?