Last active
September 4, 2021 14:18
-
-
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 file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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