当 func encode(with aCoder: NSCoder) 方法中的存档对象在实际 revice 中与 swift 枚举崩溃时

When archive object in the func encode(with aCoder: NSCoder) method crashed with swift enum in real revice

在我的 singleton class 中,我这里有一个 swift 枚举:

import UIKit

enum UserType {
    case terant  // 
    case normalUser  // 
    case normalUserFinancialer  // 
}

@objc(UserStaticSwift)
class UserStaticSwift:NSObject, NSCoding {

报道error

随着 console 日志:

libc++abi.dylib: terminating with uncaught exception of type NSException

encode中:

func encode(with aCoder: NSCoder) {
    
    aCoder.encode(islogin, forKey: "islogin")
    aCoder.encode(type!, forKey: "type")  // crash here in real device 
    aCoder.encode(forOcType, forKey: "forOcType")
    aCoder.encode(username, forKey: "username")
    aCoder.encode(password, forKey: "password")
    aCoder.encode(userId, forKey: "userId")

这里的code我存档我的userStatic:

    userStatic.addUserInfo(type: userStatic.type!, dic: userInfoDic, closure: { (void) in
            
                // success then archive `userStatic`
                let paths:NSArray = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
                let path = paths.firstObject
                let homePath = "\(path)/\(Global.archive_userStaticData)"
                
                let _ = NSKeyedArchiver.archiveRootObject(userStatic, toFile: homePath)
                
            })

我的 debugarchiveRootObject:

console日志:

(lldb) po NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray

error: Couldn't materialize: couldn't get the value of void: extracting data from value failed

error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression
(lldb) po homePath

error: Couldn't materialize: couldn't get the value of void: extracting data from value failed

error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression

我在 simulatordevice 中测试过,在 simulator 中不存在问题,实际上 device 问题出现了。

试试这个解决你的问题

func encode(with aCoder: NSCoder) {
    aCoder.encode(type.rawValue, forKey: "type")
}

了解更多信息

让我们详细讨论这个问题

例如,这是我的枚举:

enum PieceType : Int {
    case empty
    case notEmpty
}

这是我的对象,它是 NSObject

的子对象
class Piece: NSObject, NSCoding {
    var islogin: Bool
    var type: PieceType
    var username: String!
    var password: String!

    override init() {
        islogin = false
        type = PieceType.empty
        username = ""
        password = ""
    }

    required init(coder aDecoder: NSCoder) {
        islogin = aDecoder.decodeBool(forKey: "islogin")
        type = PieceType(rawValue: aDecoder.decodeObject(forKey: "type") as! Int)!
        username = aDecoder.decodeObject(forKey: "username") as! String
        password = aDecoder.decodeObject(forKey: "password") as! String

    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(islogin, forKey: "islogin")
        aCoder.encode(type.rawValue, forKey: "type")
        aCoder.encode(username, forKey: "username")
        aCoder.encode(password, forKey: "password")

    }

}

当您调用 NSKeyedArchiver.archiveRootObject(::) 时,它将调用 func encode(with aCoder: NSCoder) 方法并将您的 NSObject 转换为数据 当您尝试取消归档对象时,它将调用 init(coder aDecoder: NSCoder) 方法,并且使用 Key.

将 Data 转换为 NSObject

但在 Enum 情况下你不能直接编码 enum B'因为它是用户定义数据类型但 rawValue 必须是内置数据类型,如 Int、String、Float .....很快。 这就是为什么当你尝试编码 enum 时你需要使用 rawValue

希望你能得到分数。