NSKeyedUnarchiver fails to decode a custom object in swift
Asked Answered
M

1

6

I'm trying a basic implementation of the NSCoding protocol in swift, but it seems I can't success to unarchive an object after it has been correctly archived.

Here's my attempt

import Cocoa

class User: NSObject, NSCoding {
    var name: String

    init(name: String) {
        self.name = name
    }

    init(coder aDecoder: NSCoder!) {
        self.name = aDecoder.decodeObjectForKey("name") as String
    }

    func encodeWithCoder(aCoder: NSCoder!) {
        aCoder.encodeObject(name, forKey: "name")
    }
}

let user = User(name: "Gabriele")
let encodedUser = NSKeyedArchiver.archivedDataWithRootObject(user)
let decodedUser = NSKeyedUnarchiver.unarchiveObjectWithData(encodedUser) as User

Running this in the playground, it launches an exception on the last line. Here's the details

Execution was interrupted, reason: signal SIGABRT.
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1: tid = 0x433bc, 0x00007fff9325e37a libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff9325e37a libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff8c3618f7 libsystem_pthread.dylib`pthread_kill + 90
    frame #2: 0x00007fff935b462b libsystem_c.dylib`abort + 129
    frame #3: 0x00007fff8813fa21 libc++abi.dylib`abort_message + 257
    frame #4: 0x00007fff881679d1 libc++abi.dylib`default_terminate_handler() + 267
    frame #5: 0x00007fff8538050d libobjc.A.dylib`_objc_terminate() + 103
    frame #6: 0x00007fff881650a1 libc++abi.dylib`std::__terminate(void (*)()) + 8
    frame #7: 0x00007fff88164b30 libc++abi.dylib`__cxa_throw + 121
    frame #8: 0x00007fff8537c6a7 libobjc.A.dylib`objc_exception_throw + 341
    frame #9: 0x00007fff8ec1962d CoreFoundation`+[NSException raise:format:] + 205
    frame #10: 0x00007fff90dd9382 Foundation`_decodeObjectBinary + 2682
    frame #11: 0x00007fff90dd8796 Foundation`_decodeObject + 278
    frame #12: 0x00007fff90dfe159 Foundation`+[NSKeyedUnarchiver unarchiveObjectWithData:] + 89

The encoding works fine, as encodedUser is a valid instance of NSData (NSConcreteMutableData, to be precise).

Is this some sort of interoperability bug of Cocoa API in swift or am I implementing the NSCoding protocol wrong?

Manzano answered 5/7, 2014 at 19:37 Comment(5)
Your code seems to work fine in a compiled app, so this might be a Playground problem.Craniometer
Try @objc(User) just before your class declaration to get a non-mangled class name.Genocide
possible duplicate of Simple Swift class does not compileGenocide
@David, thanks for the pointer, but apparently my issue is different. The compiler doesn't crash and adding objc(User) doesn't help.Manzano
It's not a playground "bug" It's a limitation. Since the classes are dynamic in the playground, they don't go through the normal class loading process, so they don't get registered, so you have to explicitly register them. Read the whole question and answer I linked.Genocide
M
0

As Martin pointed out the in the comments, the code works fine in a compiled app, so it's definitely a playground bug.

David, in the comments, suggested to use @objc(User) in order to get a non-mangled class name, but it didn't help in this specific case, so - as of beta 2 - I still haven't find a workaround to make it work in the playground.

Manzano answered 6/7, 2014 at 9:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.