Skip to content

Instantly share code, notes, and snippets.

@codelynx
Last active September 4, 2021 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codelynx/9a336a96b76a39b0922457c0cc84835d to your computer and use it in GitHub Desktop.
Save codelynx/9a336a96b76a39b0922457c0cc84835d to your computer and use it in GitHub Desktop.
This code demonstrate archive and unarchive objects derived from a certain class and its descendants using NSObject and NSCoding
/*
This sample code shows the problem of archive and unarchive abstruct objects. Please see `TODO` keyword
and make this Contents class to save and load shape objects.
CASE: All target objects are based on NSObject with NSCoding to archive and unarchive Shape desendant class objects
file: archive-unarchive-1.swift
https://gist.github.com/codelynx/428b27b3cfd58b8c7382346f1a4bc415
*/
import Foundation
import CoreGraphics
protocol Shape: NSObject, NSCoding {
init?(coder: NSCoder)
func encode(with coder: NSCoder)
}
class Circle: NSObject, Shape {
var center: CGPoint
var radius: CGFloat
init(center: CGPoint, radius: CGFloat) {
self.center = center
self.radius = radius
super.init()
}
required init?(coder: NSCoder) {
self.center = coder.decodeObject(forKey: "center") as! CGPoint
self.radius = coder.decodeObject(forKey: "radius") as! CGFloat
super.init()
}
func encode(with coder: NSCoder) {
coder.encode(self.center, forKey: "center")
coder.encode(self.radius, forKey: "radius")
}
override var description: String { "{Circle: \(self.center)-\(self.radius)}" }
}
class Rectangle: NSObject, Shape {
var origin: CGPoint
var size: CGSize
init(origin: CGPoint, size: CGSize) {
self.origin = origin
self.size = size
super.init()
}
required init?(coder: NSCoder) {
self.origin = coder.decodeObject(forKey: "origin") as! CGPoint
self.size = coder.decodeObject(forKey: "size") as! CGSize
super.init()
}
func encode(with coder: NSCoder) {
coder.encode(self.origin, forKey: "origin")
coder.encode(self.size, forKey: "size")
}
override var description: String { "{Rectangle: origin=\(self.origin), size=\(self.size)}" }
}
class RoundedRectangle: Rectangle {
var cornerRadius: CGFloat
init(origin: CGPoint, size: CGSize, radius: CGFloat) {
self.cornerRadius = radius
super.init(origin: origin, size: size)
}
required init?(coder: NSCoder) {
self.cornerRadius = coder.decodeObject(forKey: "cornerRadius") as! CGFloat
super.init(coder: coder)
}
override func encode(with coder: NSCoder) {
coder.encode(self.cornerRadius, forKey: "cornerRadius")
super.encode(with: coder)
}
override var description: String { "{RoundedRectangle: origin=\(self.origin), size=\(self.size), cornerRadius=\(self.cornerRadius)}" }
}
class Contents: NSObject, NSCoding {
var shapes: [Shape]
init(shapes: [Shape]) {
self.shapes = shapes
}
required init?(coder: NSCoder) {
self.shapes = coder.decodeObject(forKey: "shapes") as! [Shape]
}
func encode(with coder: NSCoder) {
coder.encode(self.shapes, forKey: "shapes")
}
override var description: String { "{Contents:" + self.shapes.map { $0.description }.joined(separator: ",") + "}" }
}
let contents = Contents(shapes: [
Circle(center: CGPoint(x: 10, y: 20), radius: 30),
Rectangle(origin: CGPoint(x: 40, y: 50), size: CGSize(width: 60, height: 70)),
RoundedRectangle(origin: CGPoint(x: 100, y: 110), size: CGSize(width: 120, height: 130), radius: 5)
])
let data = try! NSKeyedArchiver.archivedData(withRootObject: contents, requiringSecureCoding: false)
let object = try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)
switch object {
case let circle as Circle:
print("circle:", circle.center, circle.radius)
case let rectangle as RoundedRectangle:
print("rounded rectangle:", rectangle.origin, rectangle.size)
case let rectangle as Rectangle:
print("rectangle:", rectangle.origin, rectangle.size)
case let contents as Contents:
print("contents:", contents.shapes.map { $0.description })
default:
print("unexpected object")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment