swiftnsuserdefaultssigabrtnscoding

Saving custom Swift class with NSCoding to UserDefaults


I am currently trying to save a custom Swift class to NSUserDefaults. Here is the code from my Playground:

import Foundation

class Blog : NSObject, NSCoding {

    var blogName: String?

    override init() {}

    required init(coder aDecoder: NSCoder) {
        if let blogName = aDecoder.decodeObjectForKey("blogName") as? String {
            self.blogName = blogName
        }
    }

    func encodeWithCoder(aCoder: NSCoder) {
        if let blogName = self.blogName {
            aCoder.encodeObject(blogName, forKey: "blogName")
        }
    }

}

var blog = Blog()
blog.blogName = "My Blog"

let ud = NSUserDefaults.standardUserDefaults()    
ud.setObject(blog, forKey: "blog")

When I run the code, I get the following error

Execution was interrupted, reason: signal SIGABRT.

in the last line (ud.setObject...)

The same code also crashes when in an app with the message

"Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType')"

Can anybody help? I am using Xcode 6.0.1 on Maverick. Thanks.


Solution

  • As @dan-beaulieu suggested I answer my own question:

    Here is the working code now:

    Note: Demangling of the class name was not necessary for the code to work in Playgrounds.

    import Foundation
    
    class Blog : NSObject, NSCoding {
    
        var blogName: String?
    
        override init() {}
    
        required init(coder aDecoder: NSCoder) {
            if let blogName = aDecoder.decodeObjectForKey("blogName") as? String {
                self.blogName = blogName
            }
        }
    
        func encodeWithCoder(aCoder: NSCoder) {
            if let blogName = self.blogName {
                aCoder.encodeObject(blogName, forKey: "blogName")
            }
        }
    
    }
    
    let ud = NSUserDefaults.standardUserDefaults()
    
    var blog = Blog()
    blog.blogName = "My Blog"
    
    ud.setObject(NSKeyedArchiver.archivedDataWithRootObject(blog), forKey: "blog")
    
    if let data = ud.objectForKey("blog") as? NSData {
        let unarc = NSKeyedUnarchiver(forReadingWithData: data)
        let newBlog = unarc.decodeObjectForKey("root") as Blog
    }