Swift - How to encode a Bool type with NSSecureCoding

1.9k Views Asked by At

I am having trouble saving a Bool variable using the NSSecureCoding within a Swift app.

I don't have any experience with Objective-C and I'm relatively new to Swift (I have a c# background). As I understand, using NSSecureCoding requires us to use the string and int counterparts in Objective-C - i.e. NSString and NSNumber. I was able to successfully encode and decode ints and strings this way:

// Encode
coder.encode(myString as NSString, forKey: PropertyKey.myStrKey)
coder.encode(NSNumber(value: myInt), forKey: PropertyKey.myIntKey)

// Decode
let myString = coder.decodeObject(of: NSString.self, forKey: PropertyKey.myStrKey) as String? ?? ""
let myInt = coder.decodeObject(of: NSNumber.self, forKey: PropertyKey.myIntKey)

However, I am not sure how to handle booleans. I tried this:

// Encode
coder.encode(NSNumber(value: myBool), forKey: PropertyKey.myBoolKey)

// Decode
let myBool = coder.decodeObject(of: NSNumber.self, forKey: PropertyKey.myBoolKey)

print("\(String(describing: myBool))")

But this always prints: Optional(1) irrespective of the initial value of myBool. Any help would be greatly appreciated. Thanks.

1

There are 1 best solutions below

1
On

No need to encode a String and or a NSNumber. You can simply encode your Bool and just make sure to use NSCoder's decodeBool method when decoding it.


Playground testing:

class Test: NSObject, NSSecureCoding {
    
    static var supportsSecureCoding: Bool = true

    var aBool: Bool
    
    required init(aBool: Bool) {
        self.aBool = aBool
    }
    
    func encode(with coder: NSCoder) {
        coder.encode(aBool, forKey: "aBool")
    }
    
    required init?(coder: NSCoder) {
        aBool = coder.decodeBool(forKey: "aBool")
    }
}

let test = Test(aBool: true)
do {
    let data = try NSKeyedArchiver.archivedData(withRootObject: test, requiringSecureCoding: true)
    print("data size:", data.count)  // data size: 251
    let decoded = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as! Test
    print("aBool", decoded.aBool)  // aBool true
} catch {
     print(error)
}