Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions Protocol-Oriented.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
objects = {

/* Begin PBXBuildFile section */
42B17C051B4AFBC7005676C0 /* UnsecureToSecureDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42B17C041B4AFBC7005676C0 /* UnsecureToSecureDataStore.swift */; };
42D09EA71B4855C700929DDF /* KeychainDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42D09EA61B4855C700929DDF /* KeychainDataStore.swift */; };
42D09EAA1B48599500929DDF /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42D09EA91B48599500929DDF /* Keychain.swift */; };
942D4A741B4729DC0079945E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942D4A731B4729DC0079945E /* AppDelegate.swift */; };
942D4A761B4729DC0079945E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942D4A751B4729DC0079945E /* ViewController.swift */; };
942D4A791B4729DC0079945E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 942D4A771B4729DC0079945E /* Main.storyboard */; };
942D4A7B1B4729DC0079945E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 942D4A7A1B4729DC0079945E /* Assets.xcassets */; };
942D4A7E1B4729DC0079945E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 942D4A7C1B4729DC0079945E /* LaunchScreen.storyboard */; };
94448E781B4768C300A73599 /* DataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94448E771B4768C300A73599 /* DataStore.swift */; };
94D8EEF81B482780001A68BA /* DataStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8EEF71B482780001A68BA /* DataStoreTests.swift */; };
94448E781B4768C300A73599 /* NSUserDefaults+StorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94448E771B4768C300A73599 /* NSUserDefaults+StorageType.swift */; };
94D8EEF61B481F8D001A68BA /* StorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8EEF51B481F8D001A68BA /* StorageType.swift */; };
94D8EEF81B482780001A68BA /* DataStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8EEF71B482780001A68BA /* DataStoreTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -28,18 +31,21 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
42B17C041B4AFBC7005676C0 /* UnsecureToSecureDataStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnsecureToSecureDataStore.swift; sourceTree = "<group>"; };
42D09EA61B4855C700929DDF /* KeychainDataStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainDataStore.swift; sourceTree = "<group>"; };
42D09EA91B48599500929DDF /* Keychain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Keychain.swift; path = lib/Keychain.swift; sourceTree = "<group>"; };
942D4A701B4729DC0079945E /* Protocol-Oriented.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Protocol-Oriented.app"; sourceTree = BUILT_PRODUCTS_DIR; };
942D4A731B4729DC0079945E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
942D4A751B4729DC0079945E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
942D4A751B4729DC0079945E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; usesTabs = 0; };
942D4A781B4729DC0079945E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
942D4A7A1B4729DC0079945E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
942D4A7D1B4729DC0079945E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
942D4A7F1B4729DC0079945E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
942D4A841B4729DC0079945E /* Protocol-OrientedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Protocol-OrientedTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
942D4A8A1B4729DC0079945E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
94448E771B4768C300A73599 /* DataStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataStore.swift; sourceTree = "<group>"; };
94D8EEF71B482780001A68BA /* DataStoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataStoreTests.swift; sourceTree = "<group>"; };
94448E771B4768C300A73599 /* NSUserDefaults+StorageType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSUserDefaults+StorageType.swift"; sourceTree = "<group>"; usesTabs = 0; };
94D8EEF51B481F8D001A68BA /* StorageType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageType.swift; sourceTree = "<group>"; };
94D8EEF71B482780001A68BA /* DataStoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataStoreTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -60,6 +66,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
42D09EA81B48598100929DDF /* lib */ = {
isa = PBXGroup;
children = (
42D09EA91B48599500929DDF /* Keychain.swift */,
);
name = lib;
sourceTree = "<group>";
};
942D4A671B4729DC0079945E = {
isa = PBXGroup;
children = (
Expand All @@ -68,6 +82,7 @@
942D4A711B4729DC0079945E /* Products */,
);
sourceTree = "<group>";
usesTabs = 0;
};
942D4A711B4729DC0079945E /* Products */ = {
isa = PBXGroup;
Expand All @@ -81,14 +96,17 @@
942D4A721B4729DC0079945E /* Protocol-Oriented */ = {
isa = PBXGroup;
children = (
42D09EA81B48598100929DDF /* lib */,
942D4A731B4729DC0079945E /* AppDelegate.swift */,
942D4A751B4729DC0079945E /* ViewController.swift */,
942D4A771B4729DC0079945E /* Main.storyboard */,
942D4A7A1B4729DC0079945E /* Assets.xcassets */,
942D4A7C1B4729DC0079945E /* LaunchScreen.storyboard */,
942D4A7F1B4729DC0079945E /* Info.plist */,
94448E771B4768C300A73599 /* DataStore.swift */,
94448E771B4768C300A73599 /* NSUserDefaults+StorageType.swift */,
94D8EEF51B481F8D001A68BA /* StorageType.swift */,
42D09EA61B4855C700929DDF /* KeychainDataStore.swift */,
42B17C041B4AFBC7005676C0 /* UnsecureToSecureDataStore.swift */,
);
path = "Protocol-Oriented";
sourceTree = "<group>";
Expand Down Expand Up @@ -203,9 +221,12 @@
buildActionMask = 2147483647;
files = (
942D4A761B4729DC0079945E /* ViewController.swift in Sources */,
94448E781B4768C300A73599 /* DataStore.swift in Sources */,
42D09EA71B4855C700929DDF /* KeychainDataStore.swift in Sources */,
94448E781B4768C300A73599 /* NSUserDefaults+StorageType.swift in Sources */,
42B17C051B4AFBC7005676C0 /* UnsecureToSecureDataStore.swift in Sources */,
942D4A741B4729DC0079945E /* AppDelegate.swift in Sources */,
94D8EEF61B481F8D001A68BA /* StorageType.swift in Sources */,
42D09EAA1B48599500929DDF /* Keychain.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
32 changes: 0 additions & 32 deletions Protocol-Oriented/DataStore.swift

This file was deleted.

36 changes: 36 additions & 0 deletions Protocol-Oriented/KeychainDataStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// SecureDataStore.swift
// Protocol-Oriented
//
// Created by Jeff Boek on 7/4/15.
// Copyright © 2015 pdx-ios.org. All rights reserved.
//

import Foundation

/// Keychain Store
final class KeychainDataStore: SecureStorageType {

private var keychain = Keychain(service: "org.pdx-ios")

/// Fetch an object from the keychain
func fetchObjectForKey<T : Storable>(key: String) -> T? {
guard let data = keychain.getData(key) else { return nil }
guard let object: AnyObject = NSKeyedUnarchiver.unarchiveObjectWithData(data) else { return nil }

return object as? T
}

/// Remove an object from the keychain
func removeObjectForKey(key: String) {
keychain.remove(key)
}

/// Store an object in the keychain
func storeObject<T : Storable>(object: T, forKey key: String) {
guard let object: AnyObject = object as? AnyObject else { return }
let data = NSKeyedArchiver.archivedDataWithRootObject(object)

keychain.set(data, key: key)
}
}
24 changes: 24 additions & 0 deletions Protocol-Oriented/NSUserDefaults+StorageType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// DataStore.swift
// Protocol-Oriented
//
// Created by Ryan Arana on 7/3/15.
// Copyright © 2015 pdx-ios.org. All rights reserved.
//

import Foundation

extension NSUserDefaults: StorageType {

/// Fetch an object from the Store
func fetchObjectForKey<T : Storable>(key: String) -> T? {
return objectForKey(key) as? T
}

// NSUserDefaults already implements removeObjectForKey:

/// Store object
func storeObject<T : Storable>(object: T, forKey key: String) {
setObject((object as? AnyObject), forKey: key)
}
}
26 changes: 17 additions & 9 deletions Protocol-Oriented/StorageType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,22 @@
// Copyright © 2015 pdx-ios.org. All rights reserved.
//

// DONT USE THIS IN PRODUCTION
typealias Storable = _ObjectiveCBridgeable


/// A type that can store values somewhere
protocol StorageType {
/// Adds a name to the data store.
func addName(name: String)

/// Removes the first occurence of the given `name` from the data store.
func removeName(name: String)

/// Returns all of the names stored in the data store.
func fetchNames() -> [String]
}

/// Fetch an object from the Store
func fetchObjectForKey<T: Storable>(key: String) -> T?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plz to keep all my doc strings!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstrings are 3 /s :neckbeard:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the docstring for the protocol got lost


/// Remove an object from the store
func removeObjectForKey(key: String)

/// Add an object to the store
func storeObject<T: Storable>(object: T, forKey key: String)
}

/// A type that can store values somewhere, securely
protocol SecureStorageType: StorageType { }
40 changes: 40 additions & 0 deletions Protocol-Oriented/UnsecureToSecureDataStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// UnsecureToSecureDataStore.swift
// Protocol-Oriented
//
// Created by Jeff Boek on 7/6/15.
// Copyright © 2015 pdx-ios.org. All rights reserved.
//

import Foundation

final class UnsecureToSecureDataStore: StorageType {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to have a docstring describing this class


private let secureStorage: SecureStorageType
private let unsecureStorage: StorageType

init(unsecureStorage: StorageType, secureStorage: SecureStorageType) {
self.secureStorage = secureStorage
self.unsecureStorage = unsecureStorage
}

func fetchObjectForKey<T : Storable>(key: String) -> T? {
return secureStorage.fetchObjectForKey(key) ?? migrateKey(key)
}

func removeObjectForKey(key: String) {
secureStorage.removeObjectForKey(key)
unsecureStorage.removeObjectForKey(key)
}

func storeObject<T : Storable>(object: T, forKey key: String) {
secureStorage.storeObject(object, forKey: key)
}

private func migrateKey<T: Storable>(key: String) -> T? {
guard let object: T = unsecureStorage.fetchObjectForKey(key) else { return nil }
secureStorage.storeObject(object, forKey: key)

return object
}
}
32 changes: 19 additions & 13 deletions Protocol-Oriented/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@

import UIKit


/// The key to store our data under in the data store
private let kNamesKey = "org.pdx-ios.names"

class ViewController: UIViewController {

@IBOutlet var textField: UITextField!
@IBOutlet var addButton: UIButton!
@IBOutlet var tableView: UITableView!

/// The backing data store
let dataStore: StorageType = NSUserDefaults.standardUserDefaults()

Expand All @@ -22,9 +26,9 @@ class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

// Grab all of the names from our DataStore
names = dataStore.fetchNames()
names = dataStore.fetchObjectForKey(kNamesKey) ?? []
}

@IBAction func addAction() {
Expand All @@ -33,15 +37,17 @@ class ViewController: UIViewController {

// Clear the text field
textField.text = nil

// Store the name into the dataStore
dataStore.addName(name)

names.append(name)

// Store the names into the dataStore
dataStore.storeObject(names, forKey: kNamesKey)
reloadData()
}

/// Fetch names from the dataStore and reload the tableView data
func reloadData() {
names = dataStore.fetchNames()
names = dataStore.fetchObjectForKey(kNamesKey) ?? []
tableView.reloadData()
}
}
Expand All @@ -67,12 +73,12 @@ extension ViewController: UITableViewDataSource {
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
tableView.beginUpdates()
if editingStyle == .Delete {
// Grab the name from our names property
let name = names.removeAtIndex(indexPath.row)
// Remove that name from the dataStore
dataStore.removeName(name)
// Remove that name from the list
names.removeAtIndex(indexPath.row)

// Store the names into the dataStore
dataStore.storeObject(names, forKey: kNamesKey)

// Remove the row from the tableView
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
Expand Down
Loading