Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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:

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 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.

like image 822
aircraft Avatar asked Feb 05 '23 13:02

aircraft


1 Answers

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.

like image 171
jignesh Vadadoriya Avatar answered Apr 29 '23 09:04

jignesh Vadadoriya