2017-03-13 50 views
1

目的編碼嵌套枚舉SWIFT 3

我有一個狀態屬性的用戶類,我想將其存儲到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' 

回答

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 
} 

其次,我配置了值類來實現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?

+0

感謝您的答覆,但我仍然有錯誤'終止應用程序由於未捕獲的異常'NSInvalidArgumentException',原因:' - [_ SwiftValue encodeWithCoder:]:無法識別的選擇器發送到實例0x7f940e6bec30''在這個方法** let encodedData:Data = NSKeyedArch iver.archivedData(withRootObject:self)**這是寫在用戶類內 –

+1

@StephenChen我從你的錯誤中注意到你仍然在使用'func encodeWithCoder(aCoder:NSCoder)'而不是'public func encode(with aCoder:NSCoder) '。是這種情況還是這是你以前沒有得到的新錯誤? – Prientus

+0

@Prientus對不起,我打錯了。感謝您的通知,在我的代碼中,我確實使用了'公共func編碼(使用代碼:NSCoder)' –