简体   繁体   中英

Storing OpaquePointer type in UserDefaults

I am working on Xcode 12 and Swift 5 environment to build an iOS application.

I need to store an OpaquePointer type variable("self.loggers" in the code below) before the view disappears(or before the app closes) and retrieve it when the view appears( when the app runs). I tried to use UserDefault as below,

// Storing(In viewWillDisappear)
do {
            encodedData = try NSKeyedArchiver.archivedData(withRootObject: self.loggers, requiringSecureCoding: false)
            UserDefaults.standard.set(encodedData, forKey: "accelLoggerID")
        } catch {
            print("archiving error")
        }
...

// Retrieving(In viewDidLoad)
if let decodedData = UserDefaults.standard.object(forKey: "acceleration") as? Data {
            do {
                self.loggers = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as? [String:OpaquePointer] ?? [:]} catch {
                    print("unarchiving error")
                }
        } else {
            self.loggers = [:]
            print("No value in Userdefault. [viewDidLoad]")
        }

However, NSKeyedArchiver failed to encode such type. After that, I made a class that wraps the variable.

class LoggerWrapper {
    var loggers: [String : OpaquePointer]
    init(loggerDic: [String : OpaquePointer]) {
        loggers = loggerDic
    }
}

And changed my code like

self.loggers = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(decodedData) as? LoggerWrapper ?? LoggerWrapper(loggerDic: [:])} catch {
                    print("unarchiving error")
                }

However, this gives SIGABRT when NSKeyedArchiver.archivedData is called. Is there any way to store Opaquepointer type in UserDefaults? If not, can using core data solve this problem?

Thank you.

You probably need to convert the pointers to Int bitPatterns. There is an initializer on Int for that: let intBitPattern = Int(bitPattern: opaquePointer) . There is also an initializer on OpaquePointer that takes an Int bitPattern: let opaquePointer = OpaquePointer(bitPattern: intBitPattern) . So you would need to convert the values in your dictionary (eg using compactMapValues ) before storing and after reading it.

With a Dictionary<String, Int> , you should be able to store it directly in UserDefaults, without the need for NSKeyedArchiver and NSKeyedUnarchiver .


Sidenote: Pointers aren't "long-lived". So storing it in UserDefaults is only valid during the lifetime of your app. Once your app restarts, the pointers might no longer be valid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM