编码嵌套枚举swift 3

时间:2017-03-13 14:40:12

标签: swift enums nscoder

目的

我有一个带有 status 属性的User类,我希望将它存储到NSUserDefault中,它需要先对User类进行编码。

用户类代码更新版本

 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'

1 个答案:

答案 0 :(得分:2)

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

首先,我开始给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类来实现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)
}

我还建议您在此处阅读一些相关内容:NSCodingWorkaround for Swift Enum with raw type + case arguments?