Skip to content

Instantly share code, notes, and snippets.

@stepanhruda
Last active August 29, 2015 14:16
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 stepanhruda/cf813d75b4cdf4e1c18c to your computer and use it in GitHub Desktop.
Save stepanhruda/cf813d75b4cdf4e1c18c to your computer and use it in GitHub Desktop.
Immutable values and iOS
import Foundation
protocol Identifiable {
typealias IdentifierType: Hashable, Serializable
var identifier: IdentifierType { get }
}
func isTheSameIdentity<T: Identifiable>(a: T, b: T) -> Bool {
return a.identifier == b.identifier
}
class IdentityStore<V: Identifiable where V: Serializable> {
private var defaults: NSUserDefaults
private var key: String
init(key: String) {
self.defaults = NSUserDefaults.standardUserDefaults()
self.key = key
let contents: AnyObject? = defaults.objectForKey(key)
if contents == nil {
defaults.setObject([:], forKey: key)
}
}
private var storage: [V.IdentifierType:V] {
get {
let dictionary = defaults.objectForKey(key) as NSDictionary
return deserializeNSDictionary(dictionary, V.self)
}
set { defaults.setObject(serializeSwiftDictionary(newValue), forKey: key) }
}
func all() -> [V] {
return storage.values.array
}
func add(value: V) {
storage[value.identifier] = value
}
func remove(value: V) {
removeForIdentifier(value.identifier)
}
func removeForIdentifier(identifier: V.IdentifierType) {
storage[identifier] = nil
}
func latest(value: V) -> V? {
return latestForIdentifier(value.identifier)
}
func latestForIdentifier(identifier: V.IdentifierType) -> V? {
return storage[identifier]
}
}
protocol Serializable {
func serialize() -> NSObject
class func deserialize(serialized: NSObject) -> Self
}
extension Dictionary {
init(pairs: [Element]) {
self.init()
for (k, v) in pairs {
self[k] = v
}
}
}
func serializeSwiftDictionary<I: Serializable, V: Serializable>(source: [I:V]) -> NSDictionary {
let serializedPairs = map(source) { (key, value) in (key.serialize(), value.serialize()) }
return Dictionary(pairs: serializedPairs)
}
func deserializeNSDictionary<V: Serializable where V: Identifiable>(source: NSDictionary, serializable: V.Type) -> [V.IdentifierType:V] {
let deserializedPairs = map(source) { (key, value) in (V.IdentifierType.deserialize(key as NSObject) , V.deserialize(value as NSObject)) }
return Dictionary(pairs: deserializedPairs)
}
struct Person {
var socialSecurityNumber: String
var age: Int
var salary: Int
func giveRaise() -> Person {
return Person(socialSecurityNumber: socialSecurityNumber, age: age, salary: salary + 10000)
}
}
extension Person: Equatable {}
func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.socialSecurityNumber == rhs.socialSecurityNumber
&& lhs.age == rhs.age
&& lhs.salary == rhs.salary
}
extension Person: Identifiable {
typealias IdentifierType = String
var identifier: String { get { return socialSecurityNumber } }
}
extension String: Serializable {
func serialize() -> NSObject {
return self
}
static func deserialize(serialized: NSObject) -> String {
return serialized as String
}
}
extension Person: Serializable {
func serialize() -> NSObject {
return [
"socialSecurityNumber": socialSecurityNumber,
"age": age,
"salary": salary
]
}
static func deserialize(serialized: NSObject) -> Person {
let dictionary = serialized as NSDictionary
let person = Person(
socialSecurityNumber: dictionary["socialSecurityNumber"] as String,
age: dictionary["age"] as Int,
salary: dictionary["salary"] as Int)
return person
}
}
func personStore() -> IdentityStore<Person> {
return IdentityStore<Person>(key: "employees")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment