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
Stop Objects from Colliding Using Spritekit
Difference Between Packed VS Normal Data Type
How to Set Inputview for Textfield in Swiftui
How to Get the Download Progress with the New Try Await Urlsession.Shared.Download(...)
Case Insensitive Dictionary in Swift
How to Check If a String Contains Chinese in Swift
Swiftui - How to Use Oncommand with Nsmenuitem on MACos
Swiftui: Dismiss View Within MACos Navigationview
How to Filter Events Created for the Current Date in the Realm Swift
Why Do Servicesubscribercellularproviders Return Nil? (In iOS 12)
How to Automatically Reflect Coredata+Icloud Changes in Swiftui View
How to Call Initializer for Subclass of Generic Type
Difference Between Dispatchqueue Types in Swift
How to Make a Uiview Focusable Using the Focus Engine on Apple Tv
List All Available Audio Devices
Creating Gif Image Color Maps in iOS 11
Create PDF of Dynamic Size with Typography Using Uiview Template(S)