Skip to content

Instantly share code, notes, and snippets.

@owensd owensd/kvc.swift Secret
Created Jul 14, 2015

Embed
What would you like to do?
Basic KVC implementation.
//: Playground - noun: a place where people can play
import Cocoa
struct KVCTypeInfo : Hashable {
let key: String
let type: Any.Type
// Terrible hash value, just FYI.
var hashValue: Int { return key.hashValue &* 3 }
}
func ==(lhs: KVCTypeInfo, rhs: KVCTypeInfo) -> Bool {
return lhs.key == rhs.key && lhs.type == rhs.type
}
protocol KeyValueCodable : _KeyValueCodable {
mutating func setValue<T>(value: T, forKey: String) throws
func getValue<T>(forKey: String) throws -> T
}
protocol _KeyValueCodable {
static var _codables: [KVCTypeInfo] { get }
var _kvcstore: Dictionary<String, Any> { get set }
}
extension KeyValueCodable {
mutating func setValue<T>(value: T, forKey: String) {
for codable in Self._codables {
if codable.key == forKey {
if value.dynamicType != codable.type {
fatalError("The stored type information does not match the given type.")
}
_kvcstore[forKey] = value
return
}
}
fatalError("Unable to set the value for key: \(forKey).")
}
func getValue<T>(forKey: String) -> T {
guard let stored = _kvcstore[forKey] else {
fatalError("The property is not set; default values are not supported.")
}
guard let value = stored as? T else {
fatalError("The stored value does not match the expected type.")
}
return value
}
}
struct Person : KeyValueCodable {
static var _codables: [KVCTypeInfo] { return [ _idKey, _fnameKey ]}
var _kvcstore: Dictionary<String, Any> = [:]
}
extension Person {
private static let _idKey = KVCTypeInfo(key: "id", type: Int.self)
private static let _fnameKey = KVCTypeInfo(key: "fname", type: String.self)
init(id: Int, fname: String) {
self.id = id
self.fname = fname
}
var id: Int {
get { return getValue("id") as Int }
set { setValue(newValue, forKey: "id") }
}
var fname: String {
get { return getValue("fname") as String }
set { setValue(newValue, forKey: "fname") }
}
}
var p = Person(id: 123, fname: "David")
p.id
p.fname
let id: Int = p.getValue("id")
let fname: String = p.getValue("fname")
p.setValue(21, forKey: "id")
p.setValue("Sally", forKey: "fname")
let id1: Int = p.getValue("id")
let fname1: String = p.getValue("fname")
@eonist

This comment has been minimized.

Copy link

eonist commented Aug 23, 2017

Pretty cool. Even works in swift 4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.