2

I am trying to archive a dictionary using the following code and getting error. Obviously there is something is wrong in the response dictionary I am passing but the trace doesn't tell anything. How do I nail down the root cause?

do {
    let data = try NSKeyedArchiver.archivedData(withRootObject: response, requiringSecureCoding: false)
} catch {
    NSLog("Unable to archive  \(error)")
}   

Error:

2019-07-17 19:08:38.978954+0530 MyApp-Swift[372:16845] Unable to archive  Error Domain=NSCocoaErrorDomain Code=4866 "Caught exception during archival: -[__SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x282995e00
    (
    0   CoreFoundation                      0x00000001ca149ebc  + 252
    1   libobjc.A.dylib                     0x00000001c9319a50 objc_exception_throw + 56
    2   CoreFoundation                      0x00000001ca062b14  + 0
    3   CoreFoundation                      0x00000001ca14f7bc  + 1412
    4   CoreFoundation                      0x00000001ca15146c _CF_forwarding_prep_0 + 92
    5   Foundation                          0x00000001cabc4aa8  + 1276
    6   Foundation                          0x00000001caadc3b4  + 444
    7   Foundation                          0x00000001cab08ed8  + 964
    8   Foundation                          0x00000001cabc4aa8  + 1276
    9   Foundation                          0x00000001caadc3b4  + 444
    10  Foundation                          0x0000000
9
  • 2
    Why are you even using NSKeyedArchiver in Swift? For most scenarios, using Codable and PropertyListEncoder/JSONEncoder is a much better alternative. Is response a Dictionary or NSDictionary? What is its exact type? Commented Jul 17, 2019 at 14:27
  • I am porting code from Objective C, so I didn't know about those options. Will look into alternatives. Btw, what's exactly wrong with NSKeyedArchiver in Swift? What advantages do alternatives offer? Commented Jul 17, 2019 at 15:58
  • 1
    What's wrong with NSKeyedArchiver in Swift is what I just said in my answer. None of the Swift types are NSCoding adopters. Some Swift types can be bridged to Objective-C types that are NSCoding adopters, but many cannot be. Commented Jul 17, 2019 at 15:58
  • Ok, so if I already have a file saved with data generated from NSKeyedArchiver.archivedData(withRootObject:), how do I make it backward compatible with codable property list? Commented Jul 17, 2019 at 16:00
  • You can't. You would need to include in your app, if you wanted to do that, some form of migration. Commented Jul 17, 2019 at 16:03

2 Answers 2

4

NSKeyedArchiver is for Cocoa Objective C objects only. Only NSCoding adopters can be archived with an NSKeyedArchiver. You would need an NSDictionary containing only NSCoding types. Well, you don’t have one.

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

1 Comment

I saw I was using enums in the Dictionary.
1

Just complementing matt's answer, which is absolutely right.

In my case, I was using a Struct that conformed to Codable and, to make it work, I just encoded it to a Dictionary [String: Any].

Applying it to your code, it would be something like this:

do {
    let encodedResponse = (try? JSONSerialization.jsonObject(with: JSONEncoder().encode(response))) as? [String: Any] ?? [:]
    let data = try NSKeyedArchiver.archivedData(withRootObject: encodedResponse, requiringSecureCoding: false)
} catch {
    NSLog("Unable to archive  \(error)")
}

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.