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")
    }
}

calling:

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: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance

2
  • How are you calling it? Commented Apr 8, 2017 at 19:10
  • sorry, added it Commented Apr 8, 2017 at 19:24

1 Answer 1

2

Reason

That is because the Character-typed keys in cx will be boxed as _SwiftValue objects which will be sent encodeWithCoder: which leads to the unrecognized selector exception.

See the comment at the top of SwiftValue.h:

This implements the Objective-C class that is used to carry Swift values that have been bridged to Objective-C objects without special handling. The class is opaque to user code, but is NSObject- and NSCopying- conforming and is understood by the Swift runtime for dynamic casting back to the contained type.

Solution

If you can change the type of cx to [String : Int], everything will work out of the box (no pun intended).

Otherwise you will have to convert cx in Foo.encode(with:) to something that can be encoded (like [String : Int], for instance) and vice versa in the decoding initializer.

See How do I encode Character using NSCoder in swift? and How do I encode enum using NSCoder in swift? for some code.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.