Adding Nscoding as an Extension

Adding NSCoding as an Extension

Like the documentation says, extensions can't add new designated initializers. What if there were private properties that need initialization? It would be impossible to properly initialize the type. You can add convenience initializers in an extension because by their nature, they must call a designated initializer.

Also, init(coder aDecoder: NSCoder) is specified to be a designated initializer because it is a whole different route to creating an instance. Take UIViewController for instance, it can be created using plain code or it can be created from a XIB file.

In the end, it is not possible to add an extension that implements NSCoding.

Perhaps you can create a wrapper class that contains this class and have it implement NSCoding.

NSCoding : How to create required init in inherited classes

Here is a simple example:

class Source: NSObject, NSCoding {

var name: String?

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

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

}

class RSSSource: Source {

var rssName: String?

override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(name, forKey: "rssName")
super.encodeWithCoder(aCoder)
}

required init?(coder aDecoder: NSCoder) {
rssName = aDecoder.decodeObjectForKey("rssName") as? String
super.init(coder: aDecoder)
}

}

Swift and NSCoding: Encoding an array of objects conforming to a class-only protocol

You need to declare your protocol as @objc, to place it into the Objective-C world:

@objc protocol Object: class, NSCoding {

The compiler will then know he will be able to toll-free bridge the Swift array with a NSArray, as you'll be able to build-up the array only with instances of classes derived from NSObject.

Saving extra data added to a class extension

I don't think you can do it for properties added through associated object API, because UIImage's encodeWithCoder: and initWithCoder: have no idea that your properties are there.

If you could create your custom MyUiImage by inheriting UIImage instead, you would be able to override encodeWithCoder: and initWithCoder: of your class, and encode/decode your properties along with the UIImage ones.

Saving custom Swift class with NSCoding to UserDefaults

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
}

How to add new key and value to existing keyed archives using NSCoding

Your code needs to not fail in the case that no password is present. Replace the guard let password ... part with something like this:

let decodedPassword = aDecoder.decodeObject(forKey: PropertyKey.password) as? String
let password = decodedPassword ?? "123456"

and then do

self.init(name: name, ip: ip, port: port, password: password)


Related Topics



Leave a reply



Submit