Created
April 6, 2019 19:13
-
-
Save rnapier/f7f0fa6202b0d6586af188635f54b28b to your computer and use it in GitHub Desktop.
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
import Foundation | |
protocol DataStorage { | |
subscript(identifier: String) -> Data? { get set } | |
} | |
extension UserDefaults: DataStorage { | |
subscript(identifier: String) -> Data? { | |
get { return data(forKey: identifier) } | |
set { set(newValue, forKey: identifier) } | |
} | |
} | |
class DataStore<Key: Hashable & Codable, Value: Codable> { | |
let identifier: String | |
private(set) var storage: DataStorage | |
var dictionary: [Key: Value] { | |
didSet { | |
storage[identifier] = try? PropertyListEncoder().encode(dictionary) | |
} | |
} | |
init(identifier: String, storage: DataStorage = UserDefaults.standard) { | |
self.identifier = identifier | |
self.storage = storage | |
let data = storage[identifier] ?? Data() | |
self.dictionary = (try? PropertyListDecoder().decode([Key: Value].self, | |
from: data)) ?? [:] | |
} | |
subscript(key: Key) -> Value? { | |
get { return dictionary[key] } | |
set { dictionary[key] = newValue } | |
} | |
} | |
extension DataStore: Collection { | |
typealias Index = Dictionary<Key, Value>.Index | |
typealias Element = Dictionary<Key, Value>.Element | |
func index(after i: Index) -> Index { return dictionary.index(after: i) } | |
var startIndex: Index { return dictionary.startIndex } | |
var endIndex: Index { return dictionary.endIndex } | |
subscript(position: Index) -> Element { return dictionary[position] } | |
} | |
typealias InMemoryDataStorage = [String: Data] | |
extension InMemoryDataStorage: DataStorage {} | |
extension InMemoryDataStorage { | |
func json() -> [String: String] { | |
return self.compactMapValues { String(bytes: $0, encoding: .utf8) } | |
} | |
} | |
/// A DataStoreStorage that tracks all changes | |
class TrackingDataStorage: DataStorage { | |
var storage: [String: Data] { | |
didSet { history.append(storage) } | |
} | |
init(_ storage: [String: Data] = [:]) { self.storage = storage } | |
var history: [[String: Data]] = [] | |
subscript(identifier: String) -> Data? { | |
get { return storage[identifier] } | |
set { storage[identifier] = newValue } | |
} | |
} | |
struct Contact: Codable { | |
let name: String | |
let address: String | |
let phone: String | |
} | |
let contacts = DataStore<Int, Contact>(identifier: "contacts") | |
contacts[123] = Contact(name: "Alice", | |
address: "123 Main Street", | |
phone: "(555) 555-1212") | |
let tracker = TrackingDataStorage() | |
let ds = DataStore<String, String>(identifier: "TEST", | |
storage: tracker) | |
ds["THING"] = "getem" | |
//ds["THING"] | |
////ds["THING"] = nil | |
//ds["THING"] | |
print(tracker.history) | |
struct Address: Codable { | |
let city: String | |
let state: String | |
} | |
struct User: Codable { | |
let name: String | |
let email: String | |
let id: Int | |
let address: Address | |
let age: Double | |
} | |
let users = [User(name: "alice", email: "[email protected]", id: 1, address: Address(city: "atlanta", state: "GA"), age: 12.3), | |
User(name: "bob", email: "[email protected]", id: 2, address: Address(city: "boston", state: "MA"), age: 23.4), | |
User(name: "charlie", email: "[email protected]", id: 3, address: Address(city: "chicago", state: "IL"), age: 34.5), | |
] | |
let json = try JSONEncoder().encode(users) | |
let plist = try PropertyListEncoder().encode(users) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment