Skip to content
This repository has been archived by the owner on Oct 31, 2018. It is now read-only.

Commit

Permalink
Support for NSUserDefaults
Browse files Browse the repository at this point in the history
  • Loading branch information
amberstar committed Mar 29, 2016
1 parent 52afe67 commit c854efb
Show file tree
Hide file tree
Showing 36 changed files with 1,708 additions and 20 deletions.
8 changes: 5 additions & 3 deletions Docs/KVStore.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# KVStore [WIP]

A KVStore is a hierarchical key-value store. It is a repository to store a collection of models, and values.
A KVStore is a hierarchical in-memory key-value store. It is a repository to store a collection of models, and values.
It is divided up into keys and values. A key is like a category, or a
sub-folder, which contains values, and possibly more child keys.

A KVStore Can:
A KVStore can:
- store and retrieve basic types (String, Int, etc.)
- store type safe models (decodable, encodable)

Expand All @@ -22,4 +22,6 @@ KVStore
| |
| |- VALUE
| |- VALUE
```
```


1 change: 1 addition & 0 deletions Sources/Coding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public extension Encodable {
// Encoder
//****************************************************************************//


public protocol EncoderType : class {
var data : [String : AnyObject] { get set }
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/KVStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public final class KVStore: Encodable, Decodable, EncoderType, DecoderType {

public private(set) var keys : [String : KVStore] = [:]
public var data = [String : AnyObject]()

/// Initialize a new Store with the specified value and key dictionaries
public init(values: [String : AnyObject] = [:], keys: [String : KVStore] = [:]) {
data = values
Expand Down
52 changes: 52 additions & 0 deletions Sources/NSUserDefaults+Coding.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Foundation

extension NSUserDefaults {

//****************************************************************************//
// MARK: Getters
//****************************************************************************//

public func getDecodable<T: Decodable>(key: String) -> T? {
guard let dictionary = dictionaryForKey(key) else { return nil }
return T.decode(dictionary)
}

public func getDecodable<T: Decodable>(key: String) -> [T]? {
guard let array = arrayForKey(key) else { return nil }
return sequence(array.map(T.decode))
}

public func getDecodable<T: Decodable>(key: String) -> [String : T]? {
guard let dictionary = dictionaryForKey(key) else { return nil }
return sequence(dictionary.map { T.decode($0) })
}

public func getDecodable<T: Decodable>(key: String, defaultValue: T) -> T {
return getDecodable(key) ?? defaultValue
}

public func getDecodable<T: Decodable>(key: String, defaultValue: [T]) -> [T] {
return getDecodable(key) ?? defaultValue
}

public func getDecodable<T: Decodable>(key: String, defaultValue: [String : T]
) -> [String : T] {
return getDecodable(key) ?? defaultValue
}

//****************************************************************************//
// MARK: Setters
//****************************************************************************//

public func setEncodeable<V: Encodable>(value: V, forKey key: String) {
setObject(value.encode(), forKey: key)
}

public func setValue<T: Encodable>(value: [T], forKey key: String) {
setObject(value.map { $0.encode() }, forKey: key)
}

public func setValue<T: Encodable>(value: [String : T], forKey key: String) {
setObject(value.map { $0.encode() }, forKey: key)
}
}
8 changes: 6 additions & 2 deletions State.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
961D13F61C11AE5A00F0EE1F /* Data.json in Resources */ = {isa = PBXBuildFile; fileRef = 961D13EE1C11AE5A00F0EE1F /* Data.json */; };
961D13F81C11AE5A00F0EE1F /* Data.plist in Resources */ = {isa = PBXBuildFile; fileRef = 961D13EF1C11AE5A00F0EE1F /* Data.plist */; };
9622DF981C9C8EC5009C1E6B /* NSURL+Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B8A90C1C9B6CA60086619F /* NSURL+Coding.swift */; };
9622DF9F1C9D9D74009C1E6B /* KVStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622DF941C9C8A85009C1E6B /* KVStoreTests.swift */; };
9622DFA11C9EE637009C1E6B /* KVStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622DF921C9C8A61009C1E6B /* KVStore.swift */; };
9622DFA21C9EE63A009C1E6B /* UIColor+Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B8A90D1C9B6CA60086619F /* UIColor+Coding.swift */; };
9690A0641C942C9100924F4C /* _TestProtocolConformer2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9690A0621C942C9100924F4C /* _TestProtocolConformer2.swift */; };
Expand All @@ -98,6 +97,8 @@
96B8A9491C9BEB870086619F /* Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B8A9101C9B6FD10086619F /* Conversion.swift */; };
96C5C3891B3C6988009121A1 /* MigrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041817801B124AB4002CA532 /* MigrationTests.swift */; };
96C86BFD1BC2E81800D6F0F3 /* TestProtocolConformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C86BFB1BC2E7F500D6F0F3 /* TestProtocolConformer.swift */; };
96FDF3361CAAABCB0099074C /* NSUserDefaults+Coding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96FDF3351CAAABCB0099074C /* NSUserDefaults+Coding.swift */; };
96FDF3371CAAC5420099074C /* KVStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9622DF941C9C8A85009C1E6B /* KVStoreTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -234,6 +235,7 @@
96B8A9101C9B6FD10086619F /* Conversion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Conversion.swift; sourceTree = "<group>"; };
96C86BFB1BC2E7F500D6F0F3 /* TestProtocolConformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TestProtocolConformer.swift; path = Tests/Models/TestModels/TestProtocolConformer.swift; sourceTree = "<group>"; };
96CE6B7B1B3BFDEC00D632BF /* Docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Docs; sourceTree = "<group>"; };
96FDF3351CAAABCB0099074C /* NSUserDefaults+Coding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSUserDefaults+Coding.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -407,6 +409,7 @@
96960A431C90F00B00D4E6D0 /* Sources */ = {
isa = PBXGroup;
children = (
96FDF3351CAAABCB0099074C /* NSUserDefaults+Coding.swift */,
9622DF921C9C8A61009C1E6B /* KVStore.swift */,
96B8A8F81C9AD3CC0086619F /* Coding.swift */,
96B8A9101C9B6FD10086619F /* Conversion.swift */,
Expand Down Expand Up @@ -570,6 +573,7 @@
96B8A9491C9BEB870086619F /* Conversion.swift in Sources */,
96960A5C1C90F00B00D4E6D0 /* Migration.swift in Sources */,
9622DFA11C9EE637009C1E6B /* KVStore.swift in Sources */,
96FDF3361CAAABCB0099074C /* NSUserDefaults+Coding.swift in Sources */,
9622DF981C9C8EC5009C1E6B /* NSURL+Coding.swift in Sources */,
96960A5D1C90F00B00D4E6D0 /* Model.swift in Sources */,
);
Expand Down Expand Up @@ -599,7 +603,7 @@
044F889B1AE69BD900FAB475 /* TestCollections.swift in Sources */,
04C1B9301AE9219900A85730 /* _Employee.swift in Sources */,
044F88A31AE69BD900FAB475 /* TestTypes.swift in Sources */,
9622DF9F1C9D9D74009C1E6B /* KVStoreTests.swift in Sources */,
96FDF3371CAAC5420099074C /* KVStoreTests.swift in Sources */,
96B8A9091C9AFA390086619F /* (null) in Sources */,
96A543611B63C6C8009A2B2D /* TestDictionaryComposition.swift in Sources */,
044F88A11AE69BD900FAB475 /* TestRelationships.swift in Sources */,
Expand Down
124 changes: 124 additions & 0 deletions Templates/machine.swift.motemplate
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,60 @@ extension <$typeName$> {
}
}<$endprocedure$>


<$procedure writeNSUserDefaultsSupportBlock$>
//****************************************************************************//
// MARK: NSUserDefaults support
//****************************************************************************//
extension NSUserDefaults {

public func get<$typeName$>(key: String) -> <$typeName$>? {
guard let dictionary = dictionaryForKey(key) else { return nil }
return <$typeName$>.decode(dictionary)
}

public func get<$typeName$>(key: String) -> [<$typeName$>]? {
guard let array = arrayForKey(key) else { return nil }
return sequence(array.map(<$typeName$>.decode))
}

public func get<$typeName$>(key: String) -> [String : <$typeName$>]? {
guard let dictionary = dictionaryForKey(key) else { return nil }
return sequence(dictionary.map { <$typeName$>.decode($0) })
}

public func get<$typeName$>(key: String, defaultValue: <$typeName$>) -> <$typeName$> {
return get<$typeName$>(key) ?? defaultValue
}

public func get<$typeName$>(key: String, defaultValue: [<$typeName$>]) -> [<$typeName$>] {
return getDecodable(key) ?? defaultValue
}

public func get<$typeName$>(key: String, defaultValue: [String : <$typeName$>]
) -> [String : <$typeName$>] {
return get<$typeName$>(key) ?? defaultValue
}

public func set<$typeName$>(value: <$typeName$>, forKey key: String) {
setObject(value.encode(), forKey: key)
}

public func set<$typeName$>(value: [<$typeName$>], forKey key: String) {
setObject(value.map { $0.encode() }, forKey: key)
}

public func set<$typeName$>(value: [String : <$typeName$>], forKey key: String) {
setObject(value.map { $0.encode() }, forKey: key)
}
}
<$endprocedure$>

<$procedure writeKVStoreSupportBlock$>

//****************************************************************************//
// MARK: KVStore support
//****************************************************************************//
extension KVStore {

public func get<$typeName$>(key: String) -> <$typeName$>? {
Expand Down Expand Up @@ -82,7 +134,61 @@ extension KVStore {
}
<$endprocedure$>

<$procedure writeNSUserDefaultsProtocolSupportBlock$>

//****************************************************************************//
// MARK: NSUserDefault Support
//****************************************************************************//

extension NSUserDefaults {

public func get<$typeName$>(key: String) -> <$typeName$>? {
guard let dictionary = dictionaryForKey(key) else { return nil }
return decode<$typeName$>(dictionary)
}

public func get<$typeName$>(key: String) -> [<$typeName$>]? {
guard let array = arrayForKey(key) else { return nil }
return sequence(array.map(decode<$typeName$>))
}

public func get<$typeName$>(key: String) -> [String : <$typeName$>]? {
guard let dictionary = dictionaryForKey(key) else { return nil }
return sequence(dictionary.map { decode<$typeName$>($0) })
}

public func get<$typeName$>(key: String, defaultValue: <$typeName$>) -> <$typeName$> {
return get<$typeName$>(key) ?? defaultValue
}

public func get<$typeName$>(key: String, defaultValue: [<$typeName$>]) -> [<$typeName$>] {
return get<$typeName$>(key) ?? defaultValue
}

public func get<$typeName$>(key: String, defaultValue: [String : <$typeName$>]
) -> [String : <$typeName$>] {
return get<$typeName$>(key) ?? defaultValue
}

public func set<$typeName$>(value: <$typeName$>, forKey key: String) {
setObject(value.encode(), forKey: key)
}

public func set<$typeName$>(value: [<$typeName$>], forKey key: String) {
setObject(value.map { $0.encode() }, forKey: key)
}

public func set<$typeName$>(value: [String : <$typeName$>], forKey key: String) {
setObject(value.map { $0.encode() }, forKey: key)
}
}
<$endprocedure$>


<$procedure writeKVStoreProtocolSupportBlock$>
//****************************************************************************//
// MARK: KVStore support
//****************************************************************************//
extension KVStore {
public func get<$typeName$>(key: String) -> <$typeName$>? {
let keys = seperateKeypath(key)
Expand Down Expand Up @@ -218,6 +324,7 @@ extension <$typeName$> : Encodable {
}

<$call writeVersionHashExtension $>
<$call writeNSUserDefaultsSupportBlock$>
<$call writeKVStoreSupportBlock$>
<$endprocedure$>

Expand Down Expand Up @@ -345,6 +452,7 @@ extension <$typeName$>: Encodable {
}

<$call writeVersionHashExtension $>
<$call writeNSUserDefaultsSupportBlock$>
<$call writeKVStoreSupportBlock$>
<$endprocedure$>

Expand Down Expand Up @@ -377,10 +485,25 @@ public protocol <$typeName$><$if hasSuperentity$> : <$superentity.managedObjectC

}

func decode<$typeName$>(data: AnyObject?) -> <$typeName$>? {

if let data = data as? [String : AnyObject] {
let decoder = Decoder(data: data)
guard let dataTypeKey = data["<$typeName$>"] as? String else { return nil }
if let t = decoder.<$typeName$>TypeForKey(dataTypeKey) {
return t.decode(decoder)
}
return nil
}
return nil
}


// Mark: Decoding

public extension DecoderType {


public func decode<$typeName$>(key: String) -> <$typeName$>? {
let data = self.data
let d = data[key] as? [String : AnyObject]
Expand Down Expand Up @@ -436,6 +559,7 @@ public extension EncoderType {
}
}

<$call writeNSUserDefaultsProtocolSupportBlock$>
<$call writeKVStoreProtocolSupportBlock$>
<$endprocedure$>

Expand Down
51 changes: 51 additions & 0 deletions Tests/Models/TestModels/_Company.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,57 @@ extension Company {
}
}

extension NSUserDefaults {

//****************************************************************************//
// MARK: NSUserDefault Getters
//****************************************************************************//

public func getCompany(key: String) -> Company? {
guard let dictionary = dictionaryForKey(key) else { return nil }
return Company.decode(dictionary)
}

public func getCompany(key: String) -> [Company]? {
guard let array = arrayForKey(key) else { return nil }
return sequence(array.map(Company.decode))
}

public func getCompany(key: String) -> [String : Company]? {
guard let dictionary = dictionaryForKey(key) else { return nil }
return sequence(dictionary.map { Company.decode($0) })
}

public func getCompany(key: String, defaultValue: Company) -> Company {
return getCompany(key) ?? defaultValue
}

public func getCompany(key: String, defaultValue: [Company]) -> [Company] {
return getDecodable(key) ?? defaultValue
}

public func getCompany(key: String, defaultValue: [String : Company]
) -> [String : Company] {
return getCompany(key) ?? defaultValue
}

//****************************************************************************//
// MARK: NSUserDefault Setters
//****************************************************************************//

public func setCompany(value: Company, forKey key: String) {
setObject(value.encode(), forKey: key)
}

public func setCompany(value: [Company], forKey key: String) {
setObject(value.map { $0.encode() }, forKey: key)
}

public func setCompany(value: [String : Company], forKey key: String) {
setObject(value.map { $0.encode() }, forKey: key)
}
}

extension KVStore {

public func getCompany(key: String) -> Company? {
Expand Down
Loading

0 comments on commit c854efb

Please sign in to comment.