How to encode [Character: Int] property using NSCoder in Swift 3?

import UIKit

class Foo: NSObject, NSCoding {
    var cx: [Character : Int]

    init(cx: [Character : Int]) {
        self.cx = cx
    }

    // MARK: - <NSCoding>

    required convenience init(coder aDecoder: NSCoder) {
        let cx = aDecoder.decodeObject(forKey: "cxKey") as! [Character : Int]
        self.init(cx: cx)
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(cx, forKey: "cxKey")
    }
}

      

vocation:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        var foo = Foo(cx: ["C": 5, "X": 6])

        let encodedData = NSKeyedArchiver.archivedData(withRootObject: foo)
        print("encodedData: \(encodedData))")

        if let foo1 = NSKeyedUnarchiver.unarchiveObject(with: encodedData) as? Foo {
            print("cx = ", foo1.cx)
        } else{
            print("There is an issue")
        }
    }
}

      

Xcode throws an error: *** Application terminated due to unmapped "NSInvalidArgumentException", reason: '- [_ SwiftValue encodeWithCoder:]: unrecognized selector posted to instance

+3


source to share


1 answer


Cause

This is because the keys Character

in cx

will be marked as _SwiftValue

objects to be sent encodeWithCoder:

, resulting in an unrecognized exception being thrown.

See the comment at the top of SwiftValue.h :

This implements the Objective-C class, which is used to wrap Swift values ​​that have been bound to Objective-C objects without special handling. The class is opaque to user code, but NSObject

- and NSCopying

- is matched and understood at runtime by Swift to dynamically cast back to the contained type.



Decision

If you can change the type cx

to [String : Int]

, everything will work out of the box (no pun intended).

Otherwise, you will need to convert cx

to Foo.encode(with:)

to something that can be encoded (for example [String : Int]

, for example) and vice versa in the decode initializer.

See How to encode a character using NSCoder in swift? and How to encode an enum using NSCoder in swift? for some code.

+2


source







All Articles