When archive object in the func encode(with aCoder

2019-02-23 08:04发布

In my singleton class, I have a swift enum here:

import UIKit

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

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

The reported error:

the error

With the console log:

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

In the 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")

The code here I archive my 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)

            })

My debug when archiveRootObject:

The console

The console log:

(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

I have tested in simulator and device, in the simulator the issue not exist, in real device the issue comes out.

1条回答
欢心
2楼-- · 2019-02-23 08:31

Try this for your Question

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

For More Information

Let Discuss this problem in details

For example, this is my Enum:

enum PieceType : Int {
    case empty
    case notEmpty
}

And this is my Object which is child of 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")

    }

}

When you call NSKeyedArchiver.archiveRootObject(::) it will call func encode(with aCoder: NSCoder) method and convert your NSObject to Data And when you try to Unarchive your object it will call init(coder aDecoder: NSCoder) method and convert Data to NSObject by using Key.

But in Enum case you can not encode enum directly B'Coz it is User Define data type but rawValue is must be inbuilt data type like Int, String,Float.....So on. that's why when you try to encode enum you need to use rawValue

I Hope you will get point.

查看更多
登录 后发表回答