Skip to content

Instantly share code, notes, and snippets.

@gilesvangruisen
Last active August 29, 2015 14:17
Show Gist options
  • Select an option

  • Save gilesvangruisen/30c95af0d3ad372ecdc0 to your computer and use it in GitHub Desktop.

Select an option

Save gilesvangruisen/30c95af0d3ad372ecdc0 to your computer and use it in GitHub Desktop.

Revisions

  1. gilesvangruisen revised this gist Mar 23, 2015. 1 changed file with 13 additions and 5 deletions.
    18 changes: 13 additions & 5 deletions LocalStoreSpec.swift
    Original file line number Diff line number Diff line change
    @@ -37,14 +37,22 @@ class LocalStoreSpec: QuickSpec {
    // Passing LocalStore set & get test
    override func spec() {
    describe("Setting and getting from LocalStore") {
    let personToStore = Person(name: "Giles")
    store.setValueForKey(personToStore, key: "person")

    let storedPerson = store.valueForKey("Giles") // Returns Deferred<Person>
    let store = LocalStore<Person>(name: "PersonStore")
    let personValue = Person(name: "Giles") // sample Person
    store.setValueForKey(personValue, key: "person")

    storedPerson.then { (person: Person) in
    expect(person.name).to(equal("Giles"))
    let deferredPerson = store.valueForKey("person") // returns Deferred<Person>
    var personFromCache = Person(name: "Someone")

    deferredPerson.then({ (person: Person) -> () in
    personFromCache = person
    })

    it("should return the same person") {
    expect(personFromCache.name).toEventually(equal("Giles"), timeout: 1, pollInterval: 0.1)
    }

    }
    }
    }
  2. gilesvangruisen revised this gist Mar 23, 2015. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions LocalStoreSpec.swift
    Original file line number Diff line number Diff line change
    @@ -39,9 +39,10 @@ class LocalStoreSpec: QuickSpec {
    describe("Setting and getting from LocalStore") {
    let personToStore = Person(name: "Giles")
    store.setValueForKey(personToStore, key: "person")
    let storedPerson = store.valueForKey("Giles")

    storedPerson.then { person in
    let storedPerson = store.valueForKey("Giles") // Returns Deferred<Person>

    storedPerson.then { (person: Person) in
    expect(person.name).to(equal("Giles"))
    }
    }
  3. gilesvangruisen revised this gist Mar 23, 2015. 1 changed file with 49 additions and 0 deletions.
    49 changes: 49 additions & 0 deletions LocalStoreSpec.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,49 @@
    //
    // LocalStoreSpec.swift
    // FPAPI
    //
    // Created by Giles Van Gruisen on 3/23/15.
    // Copyright (c) 2015 Remarkable.io. All rights reserved.
    //

    import Foundation
    import FPAPI
    import Deferred
    import Quick
    import Nimble

    // TODO: Replace with Product
    // Simple model for testing
    struct Person {
    let name: String

    static func create(name: String) -> Person {
    return Person(name: name)
    }
    }

    extension Person: StorableValue {
    static func decode(decoder: NSCoder) -> Person {
    return Person(name: decoder.decodeObjectForKey("name") as String)
    }

    func encode(coder: NSCoder) {
    coder.encodeObject(name, forKey: "name")
    }
    }

    class LocalStoreSpec: QuickSpec {

    // Passing LocalStore set & get test
    override func spec() {
    describe("Setting and getting from LocalStore") {
    let personToStore = Person(name: "Giles")
    store.setValueForKey(personToStore, key: "person")
    let storedPerson = store.valueForKey("Giles")

    storedPerson.then { person in
    expect(person.name).to(equal("Giles"))
    }
    }
    }
    }
  4. gilesvangruisen revised this gist Mar 23, 2015. 1 changed file with 68 additions and 0 deletions.
    68 changes: 68 additions & 0 deletions LocalStore.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,68 @@
    //
    // LocalStore.swift
    // FPAPI
    //
    // Created by Giles Van Gruisen on 3/23/15.
    // Copyright (c) 2015 Remarkable.io. All rights reserved.
    //

    import Foundation
    import AwesomeCache
    import Deferred

    public struct LocalStore<T: StorableValue> {

    let cache: Cache<NSData>
    let storeQueue: dispatch_queue_t

    public init(name: String) {
    self.cache = Cache<NSData>(name: name)
    self.storeQueue = dispatch_queue_create("com.fashionProject.fpapi.\(name)Cache", DISPATCH_QUEUE_SERIAL)
    }

    public func valueForKey(key: String) -> Deferred<T> {

    // Defer and return immediately because AwesomeCache is synchronous
    let deferred = Deferred<T>()

    // Make async (AwesomeCache should really handle async
    dispatch_async(self.storeQueue) {

    // Perform cache lookup
    let possibleValueData = self.cache.objectForKey(key)

    // Check for value
    if let valueData = possibleValueData {

    // Value found -> decode and resolve
    let value = StoredValue<T>(data: valueData).decode()
    deferred.resolve(value)

    } else {

    // No value found -> reject
    deferred.reject(NSError(domain: "LocalStore", code: 0, userInfo: ["EmptyKey": key]))
    }
    }

    return deferred
    }

    public func setValueForKey(value: T, key: String) -> Deferred<T> {

    // Defer and return immediately because AwesomeCache is synchronous
    let deferred = Deferred<T>()

    // Build StoredValue to convert to data
    let storedValueData = StoredValue<T>(value: value).data

    // TODO: Update AwesomeCache to give write feedback instead of blindly resolving
    self.cache.setObject(storedValueData, forKey: key)

    // Resolve with saved value
    deferred.resolve(value)

    return deferred
    }

    }
  5. gilesvangruisen revised this gist Mar 23, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ import Foundation
    /**
    The StorableValue protocol declares two functions
    for encoding and decoding a Swift value type
    because is NSCoding is restricted to class types.
    because NSCoding is restricted to class types.
    */
    public protocol StorableValue {
    class func decode(decoder: NSCoder) -> Self
  6. gilesvangruisen revised this gist Mar 23, 2015. 1 changed file with 27 additions and 28 deletions.
    55 changes: 27 additions & 28 deletions StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -6,53 +6,52 @@
    // Copyright (c) 2015 Remarkable.io. All rights reserved.
    //

    /**
    NOTICE: Ignore Gist's weird protocol syntax highlighting, this does compile.
    */

    import Foundation

    /**
    The StorableValue protocol declares two functions for
    encoding and decoding a Swift data structure to NSData
    The StorableValue protocol declares two functions
    for encoding and decoding a Swift value type
    because is NSCoding is restricted to class types.
    */
    protocol StorableValue {
    typealias DecodedType = Self
    class func decode(json: NSData) -> DecodedType
    func encode() -> NSData
    public protocol StorableValue {
    class func decode(decoder: NSCoder) -> Self
    func encode(coder: NSCoder)
    }

    /**
    The StoredValue final class defines an NSCoding
    conforming object used to encode/decode and box
    a StorableValue so that it may be archived and
    unarchived to/from any NSData cache.
    StoredValue defines a generic class defines a
    generic class used to encode/decode and box data
    from any StorableValue to make caching easier.
    */
    final class StoredValue<T: StorableValue>: NSObject, NSCoding {
    private var data = NSData()
    final public class StoredValue<T: StorableValue> {

    convenience init(value: T) {
    self.init()
    encode(value)
    private var mutableData = NSMutableData()
    public var data: NSData {
    get {
    return NSData(data: mutableData)
    }
    }

    // MARK: NSCoding
    convenience init(coder aDecoder: NSCoder) {
    self.init()
    self.data = aDecoder.decodeDataObject()!
    public init(value: T) {
    encode(value)
    }

    func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeDataObject(self.data)
    public init(data: NSData) {
    mutableData = NSMutableData(data: data)
    }

    // Set value
    func encode(value: T) {
    self.data = value.encode()
    let archiver = NSKeyedArchiver(forWritingWithMutableData: mutableData)
    value.encode(archiver)
    archiver.finishEncoding()
    }

    // Access value
    func decode() -> T.DecodedType {
    return T.decode(self.data)
    func decode() -> T {
    let unarchiver = NSKeyedUnarchiver(forReadingWithData: mutableData)
    let value = T.decode(unarchiver)
    unarchiver.finishDecoding()
    return value
    }
    }
  7. gilesvangruisen revised this gist Mar 20, 2015. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -6,6 +6,10 @@
    // Copyright (c) 2015 Remarkable.io. All rights reserved.
    //

    /**
    NOTICE: Ignore Gist's weird protocol syntax highlighting, this does compile.
    */

    import Foundation

    /**
  8. gilesvangruisen revised this gist Mar 20, 2015. 1 changed file with 12 additions and 4 deletions.
    16 changes: 12 additions & 4 deletions StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,11 @@
    //
    // StoredValue.swift
    // FPAPI
    //
    // Created by Giles Van Gruisen on 3/20/15.
    // Copyright (c) 2015 Remarkable.io. All rights reserved.
    //

    import Foundation

    /**
    @@ -6,8 +14,8 @@ encoding and decoding a Swift data structure to NSData
    */
    protocol StorableValue {
    typealias DecodedType = Self
    //class func decode(json: NSData) -> Self?
    //func encode() -> NSData
    class func decode(json: NSData) -> DecodedType
    func encode() -> NSData
    }

    /**
    @@ -40,7 +48,7 @@ final class StoredValue<T: StorableValue>: NSObject, NSCoding {
    }

    // Access value
    func decode() -> T? {
    func decode() -> T.DecodedType {
    return T.decode(self.data)
    }
    }
    }
  9. gilesvangruisen revised this gist Mar 20, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ encoding and decoding a Swift data structure to NSData
    */
    protocol StorableValue {
    typealias DecodedType = Self
    class func decode(json: NSData) -> Self?
    //class func decode(json: NSData) -> Self?
    //func encode() -> NSData
    }

  10. gilesvangruisen revised this gist Mar 20, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@ encoding and decoding a Swift data structure to NSData
    protocol StorableValue {
    typealias DecodedType = Self
    class func decode(json: NSData) -> Self?
    func encode() -> NSData
    //func encode() -> NSData
    }

    /**
  11. gilesvangruisen revised this gist Mar 20, 2015. 1 changed file with 27 additions and 31 deletions.
    58 changes: 27 additions & 31 deletions StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -1,50 +1,46 @@
    /**
    The StorableValue protocol declares two functions for
    import Foundation

    /**
    The StorableValue protocol declares two functions for
    encoding and decoding a Swift data structure to NSData
    */
    protocol StorableValue {
    typealias DecodedType = Self
    public static func decode(json: NSData) -> DecodedType?
    public func encode() -> NSData
    class func decode(json: NSData) -> Self?
    func encode() -> NSData
    }

    /**
    The StoredValue final class defines an object used to
    encode and box a StorableValue so that it may be
    archived and unarchived to/from any NSData cache.

    NSCoding extension follows.
    The StoredValue final class defines an NSCoding
    conforming object used to encode/decode and box
    a StorableValue so that it may be archived and
    unarchived to/from any NSData cache.
    */
    final class StoredValue<T: StorableValue> {
    final class StoredValue<T: StorableValue>: NSObject, NSCoding {
    private var data = NSData()

    init(T: value) {
    setValue(value)
    convenience init(value: T) {
    self.init()
    encode(value)
    }

    // Set value
    setValue(value: T) {
    self.data = value.encode()
    // MARK: NSCoding
    convenience init(coder aDecoder: NSCoder) {
    self.init()
    self.data = aDecoder.decodeDataObject()!
    }

    // Access value
    value() -> T? {
    return T.decode(data: self.data)
    func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeDataObject(self.data)
    }
    }

    /**
    Extension on StoredValue to conform to NSCoding, the
    NSData encoding/decoding protocol used by the majority
    of caches available to use in iOS and OS X apps.
    */
    extension StoredValue: NSCoding {
    // MARK: NSCoding
    required init(coder aDecoder: NSCoder) {
    self.data = coder.decodeDataObject()
    // Set value
    func encode(value: T) {
    self.data = value.encode()
    }

    func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeDataObject(self.data)
    // Access value
    func decode() -> T? {
    return T.decode(self.data)
    }
    }
    }
  12. gilesvangruisen revised this gist Mar 20, 2015. 1 changed file with 19 additions and 1 deletion.
    20 changes: 19 additions & 1 deletion StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,21 @@
    /**
    The StorableValue protocol declares two functions for
    encoding and decoding a Swift data structure to NSData
    */
    protocol StorableValue {
    typealias DecodedType = Self
    public static func decode(json: NSData) -> DecodedType?
    public func encode() -> NSData
    }

    final class StoredValue<T: StorableValue>: NSCoding {
    /**
    The StoredValue final class defines an object used to
    encode and box a StorableValue so that it may be
    archived and unarchived to/from any NSData cache.

    NSCoding extension follows.
    */
    final class StoredValue<T: StorableValue> {
    private var data = NSData()

    init(T: value) {
    @@ -20,7 +31,14 @@ final class StoredValue<T: StorableValue>: NSCoding {
    value() -> T? {
    return T.decode(data: self.data)
    }
    }

    /**
    Extension on StoredValue to conform to NSCoding, the
    NSData encoding/decoding protocol used by the majority
    of caches available to use in iOS and OS X apps.
    */
    extension StoredValue: NSCoding {
    // MARK: NSCoding
    required init(coder aDecoder: NSCoder) {
    self.data = coder.decodeDataObject()
  13. gilesvangruisen renamed this gist Mar 20, 2015. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion StoredValue → StoredValue.swift
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    protocol StorableValue {
    typealias DecodedType = Self
    public static func decode(json: NSData) -> DecodedType?
  14. gilesvangruisen created this gist Mar 20, 2015.
    33 changes: 33 additions & 0 deletions StoredValue
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,33 @@

    protocol StorableValue {
    typealias DecodedType = Self
    public static func decode(json: NSData) -> DecodedType?
    public func encode() -> NSData
    }

    final class StoredValue<T: StorableValue>: NSCoding {
    private var data = NSData()

    init(T: value) {
    setValue(value)
    }

    // Set value
    setValue(value: T) {
    self.data = value.encode()
    }

    // Access value
    value() -> T? {
    return T.decode(data: self.data)
    }

    // MARK: NSCoding
    required init(coder aDecoder: NSCoder) {
    self.data = coder.decodeDataObject()
    }

    func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeDataObject(self.data)
    }
    }