├── .gitignore
├── img
├── .DS_Store
├── img_1.png
├── img_2.png
├── img_3.png
├── img_4.png
├── img_5.png
├── img_6.png
├── img_7.png
├── img_8.png
├── img_9.png
├── img_10.png
└── img_11.png
├── Todo
├── Todo.xcodeproj
│ ├── xcuserdata
│ │ ├── marcusmolchany.xcuserdatad
│ │ │ ├── xcdebugger
│ │ │ │ └── Breakpoints_v2.xcbkptlist
│ │ │ └── xcschemes
│ │ │ │ ├── xcschememanagement.plist
│ │ │ │ └── Todo.xcscheme
│ │ └── jadekler.xcuserdatad
│ │ │ └── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── Todo.xcscheme
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcuserdata
│ │ │ ├── jadekler.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ │ └── marcusmolchany.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ └── xcshareddata
│ │ │ └── Todo.xccheckout
│ └── project.pbxproj
├── Todo
│ ├── TodoListTableViewController.h
│ ├── TodoItem.swift
│ ├── ViewController.swift
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ ├── AddTodoItemViewController.swift
│ ├── Info.plist
│ ├── AppDelegate.swift
│ ├── TodoListTableTableViewController.swift
│ └── Base.lproj
│ │ └── Main.storyboard
└── TodoTests
│ ├── Info.plist
│ └── TodoTests.swift
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea/
3 |
--------------------------------------------------------------------------------
/img/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/.DS_Store
--------------------------------------------------------------------------------
/img/img_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_1.png
--------------------------------------------------------------------------------
/img/img_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_2.png
--------------------------------------------------------------------------------
/img/img_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_3.png
--------------------------------------------------------------------------------
/img/img_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_4.png
--------------------------------------------------------------------------------
/img/img_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_5.png
--------------------------------------------------------------------------------
/img/img_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_6.png
--------------------------------------------------------------------------------
/img/img_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_7.png
--------------------------------------------------------------------------------
/img/img_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_8.png
--------------------------------------------------------------------------------
/img/img_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_9.png
--------------------------------------------------------------------------------
/img/img_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_10.png
--------------------------------------------------------------------------------
/img/img_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/img/img_11.png
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/xcuserdata/marcusmolchany.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Todo/Todo/TodoListTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TodoListTableViewController.h
3 | // Todo
4 | //
5 |
6 | @interface TodoListTableViewController
7 |
8 | -(IBAction) unwindToList:(UIStoryboardSegue *) segue;
9 |
10 | @end
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/project.xcworkspace/xcuserdata/jadekler.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/Todo/Todo.xcodeproj/project.xcworkspace/xcuserdata/jadekler.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/project.xcworkspace/xcuserdata/marcusmolchany.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeanbza/git-swift-todo-tutorial/HEAD/Todo/Todo.xcodeproj/project.xcworkspace/xcuserdata/marcusmolchany.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Todo/Todo/TodoItem.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | class TodoItem: NSObject {
4 | let itemName: String
5 | var completed: Bool
6 |
7 | init(itemName: String, completed: Bool = false) {
8 | self.itemName = itemName
9 | self.completed = completed
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Todo/Todo/ViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | class ViewController: UIViewController {
4 | override func viewDidLoad() {
5 | super.viewDidLoad()
6 | // Do any additional setup after loading the view, typically from a nib.
7 | }
8 |
9 | override func didReceiveMemoryWarning() {
10 | super.didReceiveMemoryWarning()
11 | // Dispose of any resources that can be recreated.
12 | }
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/Todo/Todo/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Todo/Todo/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/xcuserdata/jadekler.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Todo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | E852EBB91973570100DC53E7
16 |
17 | primary
18 |
19 |
20 | E852EBCB1973570100DC53E7
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/xcuserdata/marcusmolchany.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Todo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | E852EBB91973570100DC53E7
16 |
17 | primary
18 |
19 |
20 | E852EBCB1973570100DC53E7
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Todo/Todo/AddTodoItemViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | class AddTodoItemViewController: UIViewController {
4 | var todoItem: TodoItem = TodoItem(itemName: "")
5 |
6 | @IBOutlet var doneButton: UIBarButtonItem!
7 | @IBOutlet var textField: UITextField!
8 |
9 | required init?(coder aDecoder: NSCoder) {
10 | super.init(coder: aDecoder)
11 | }
12 |
13 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
14 | if (self.textField.text != "") {
15 | self.todoItem = TodoItem(itemName: self.textField.text!)
16 | }
17 | }
18 |
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 | }
22 |
23 | override func didReceiveMemoryWarning() {
24 | super.didReceiveMemoryWarning()
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Todo/TodoTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Todo/TodoTests/TodoTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TodoTests.swift
3 | // TodoTests
4 | //
5 |
6 | import UIKit
7 | import XCTest
8 |
9 | class TodoTests: XCTestCase {
10 |
11 | override func setUp() {
12 | super.setUp()
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 | }
15 |
16 | override func tearDown() {
17 | // Put teardown code here. This method is called after the invocation of each test method in the class.
18 | super.tearDown()
19 | }
20 |
21 | func testExample() {
22 | // This is an example of a functional test case.
23 | XCTAssert(true, "Pass")
24 | }
25 |
26 | func testPerformanceExample() {
27 | // This is an example of a performance test case.
28 | self.measureBlock() {
29 | // Put the code you want to measure the time of here.
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Todo/Todo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Jean de Klerk
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/project.xcworkspace/xcshareddata/Todo.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | 95915989-30C2-4992-AA30-94367A0EBE1E
9 | IDESourceControlProjectName
10 | Todo
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 171CF2FC691A30B6EDEF345EE5D38C137643414F
14 | https://github.com/jadekler/git-swift-todo-tutorial.git
15 |
16 | IDESourceControlProjectPath
17 | Todo/Todo.xcodeproj
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 171CF2FC691A30B6EDEF345EE5D38C137643414F
21 | ../../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/jadekler/git-swift-todo-tutorial.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | 171CF2FC691A30B6EDEF345EE5D38C137643414F
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 171CF2FC691A30B6EDEF345EE5D38C137643414F
36 | IDESourceControlWCCName
37 | git-swift-todo-tutorial
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Todo/Todo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | @UIApplicationMain
4 | class AppDelegate: UIResponder, UIApplicationDelegate {
5 | var window: UIWindow?
6 |
7 | func applicationWillResignActive(application: UIApplication!) {
8 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
9 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
10 | }
11 |
12 | func applicationDidEnterBackground(application: UIApplication!) {
13 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
14 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
15 | }
16 |
17 | func applicationWillEnterForeground(application: UIApplication!) {
18 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
19 | }
20 |
21 | func applicationDidBecomeActive(application: UIApplication!) {
22 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
23 | }
24 |
25 | func applicationWillTerminate(application: UIApplication!) {
26 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/Todo/Todo/TodoListTableTableViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | class TodoListTableViewController: UITableViewController {
4 |
5 | var todoItems: [TodoItem] = []
6 |
7 | @IBAction func unwindAndAddToList(segue: UIStoryboardSegue) {
8 | let source = segue.sourceViewController as! AddTodoItemViewController
9 | let todoItem:TodoItem = source.todoItem
10 |
11 | if todoItem.itemName != "" {
12 | self.todoItems.append(todoItem)
13 | self.tableView.reloadData()
14 | }
15 | }
16 |
17 | @IBAction func unwindToList(segue: UIStoryboardSegue) {
18 |
19 | }
20 |
21 | func loadInitialData() {
22 | todoItems = [
23 | TodoItem(itemName: "Go to the dentist"),
24 | TodoItem(itemName: "Fetch groceries"),
25 | TodoItem(itemName: "Sleep")
26 | ]
27 | }
28 |
29 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
30 | tableView.deselectRowAtIndexPath(indexPath, animated: false)
31 |
32 | let tappedItem = todoItems[indexPath.row] as TodoItem
33 | tappedItem.completed = !tappedItem.completed
34 |
35 | tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
36 |
37 | }
38 |
39 | override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
40 | let foo = tableView!.dequeueReusableCellWithIdentifier("ListPrototypeCell") as UITableViewCell?
41 | let tempCell = foo!
42 | let todoItem = todoItems[indexPath.row]
43 |
44 | // Downcast from UILabel? to UILabel
45 | let cell = tempCell.textLabel as UILabel!
46 | cell.text = todoItem.itemName
47 |
48 | if (todoItem.completed) {
49 | tempCell.accessoryType = UITableViewCellAccessoryType.Checkmark;
50 | } else {
51 | tempCell.accessoryType = UITableViewCellAccessoryType.None;
52 | }
53 |
54 | return tempCell
55 | }
56 |
57 | override func viewDidLoad() {
58 | super.viewDidLoad()
59 | loadInitialData()
60 | }
61 |
62 | override func didReceiveMemoryWarning() {
63 | super.didReceiveMemoryWarning()
64 | }
65 |
66 | override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
67 | return 1
68 | }
69 |
70 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
71 | return todoItems.count
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/xcuserdata/marcusmolchany.xcuserdatad/xcschemes/Todo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/xcuserdata/jadekler.xcuserdatad/xcschemes/Todo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
78 |
80 |
86 |
87 |
88 |
89 |
90 |
91 |
97 |
99 |
105 |
106 |
107 |
108 |
110 |
111 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/Todo/Todo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/Todo/Todo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | E852EBC01973570100DC53E7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E852EBBF1973570100DC53E7 /* AppDelegate.swift */; };
11 | E852EBC21973570100DC53E7 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E852EBC11973570100DC53E7 /* ViewController.swift */; };
12 | E852EBC51973570100DC53E7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E852EBC31973570100DC53E7 /* Main.storyboard */; };
13 | E852EBC71973570100DC53E7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E852EBC61973570100DC53E7 /* Images.xcassets */; };
14 | E852EBD31973570100DC53E7 /* TodoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E852EBD21973570100DC53E7 /* TodoTests.swift */; };
15 | E852EBDD1973718800DC53E7 /* AddTodoItemViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E852EBDC1973718800DC53E7 /* AddTodoItemViewController.swift */; };
16 | E852EBDF197373E700DC53E7 /* TodoListTableTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E852EBDE197373E700DC53E7 /* TodoListTableTableViewController.swift */; };
17 | E87E98B21974B478000C2B39 /* TodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87E98B11974B478000C2B39 /* TodoItem.swift */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXContainerItemProxy section */
21 | E852EBCD1973570100DC53E7 /* PBXContainerItemProxy */ = {
22 | isa = PBXContainerItemProxy;
23 | containerPortal = E852EBB21973570100DC53E7 /* Project object */;
24 | proxyType = 1;
25 | remoteGlobalIDString = E852EBB91973570100DC53E7;
26 | remoteInfo = Todo;
27 | };
28 | /* End PBXContainerItemProxy section */
29 |
30 | /* Begin PBXFileReference section */
31 | E852EBBA1973570100DC53E7 /* Todo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Todo.app; sourceTree = BUILT_PRODUCTS_DIR; };
32 | E852EBBE1973570100DC53E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | E852EBBF1973570100DC53E7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
34 | E852EBC11973570100DC53E7 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
35 | E852EBC41973570100DC53E7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
36 | E852EBC61973570100DC53E7 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
37 | E852EBCC1973570100DC53E7 /* TodoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TodoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
38 | E852EBD11973570100DC53E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
39 | E852EBD21973570100DC53E7 /* TodoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoTests.swift; sourceTree = ""; };
40 | E852EBDC1973718800DC53E7 /* AddTodoItemViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddTodoItemViewController.swift; sourceTree = ""; };
41 | E852EBDE197373E700DC53E7 /* TodoListTableTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TodoListTableTableViewController.swift; sourceTree = ""; };
42 | E87E98B11974B478000C2B39 /* TodoItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TodoItem.swift; sourceTree = ""; };
43 | /* End PBXFileReference section */
44 |
45 | /* Begin PBXFrameworksBuildPhase section */
46 | E852EBB71973570100DC53E7 /* Frameworks */ = {
47 | isa = PBXFrameworksBuildPhase;
48 | buildActionMask = 2147483647;
49 | files = (
50 | );
51 | runOnlyForDeploymentPostprocessing = 0;
52 | };
53 | E852EBC91973570100DC53E7 /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | );
58 | runOnlyForDeploymentPostprocessing = 0;
59 | };
60 | /* End PBXFrameworksBuildPhase section */
61 |
62 | /* Begin PBXGroup section */
63 | E852EBB11973570100DC53E7 = {
64 | isa = PBXGroup;
65 | children = (
66 | E852EBBC1973570100DC53E7 /* Todo */,
67 | E852EBCF1973570100DC53E7 /* TodoTests */,
68 | E852EBBB1973570100DC53E7 /* Products */,
69 | );
70 | sourceTree = "";
71 | };
72 | E852EBBB1973570100DC53E7 /* Products */ = {
73 | isa = PBXGroup;
74 | children = (
75 | E852EBBA1973570100DC53E7 /* Todo.app */,
76 | E852EBCC1973570100DC53E7 /* TodoTests.xctest */,
77 | );
78 | name = Products;
79 | sourceTree = "";
80 | };
81 | E852EBBC1973570100DC53E7 /* Todo */ = {
82 | isa = PBXGroup;
83 | children = (
84 | E852EBBF1973570100DC53E7 /* AppDelegate.swift */,
85 | E852EBC11973570100DC53E7 /* ViewController.swift */,
86 | E852EBC31973570100DC53E7 /* Main.storyboard */,
87 | E87E98B11974B478000C2B39 /* TodoItem.swift */,
88 | E852EBDE197373E700DC53E7 /* TodoListTableTableViewController.swift */,
89 | E852EBDC1973718800DC53E7 /* AddTodoItemViewController.swift */,
90 | E852EBC61973570100DC53E7 /* Images.xcassets */,
91 | E852EBBD1973570100DC53E7 /* Supporting Files */,
92 | );
93 | path = Todo;
94 | sourceTree = "";
95 | };
96 | E852EBBD1973570100DC53E7 /* Supporting Files */ = {
97 | isa = PBXGroup;
98 | children = (
99 | E852EBBE1973570100DC53E7 /* Info.plist */,
100 | );
101 | name = "Supporting Files";
102 | sourceTree = "";
103 | };
104 | E852EBCF1973570100DC53E7 /* TodoTests */ = {
105 | isa = PBXGroup;
106 | children = (
107 | E852EBD21973570100DC53E7 /* TodoTests.swift */,
108 | E852EBD01973570100DC53E7 /* Supporting Files */,
109 | );
110 | path = TodoTests;
111 | sourceTree = "";
112 | };
113 | E852EBD01973570100DC53E7 /* Supporting Files */ = {
114 | isa = PBXGroup;
115 | children = (
116 | E852EBD11973570100DC53E7 /* Info.plist */,
117 | );
118 | name = "Supporting Files";
119 | sourceTree = "";
120 | };
121 | /* End PBXGroup section */
122 |
123 | /* Begin PBXNativeTarget section */
124 | E852EBB91973570100DC53E7 /* Todo */ = {
125 | isa = PBXNativeTarget;
126 | buildConfigurationList = E852EBD61973570100DC53E7 /* Build configuration list for PBXNativeTarget "Todo" */;
127 | buildPhases = (
128 | E852EBB61973570100DC53E7 /* Sources */,
129 | E852EBB71973570100DC53E7 /* Frameworks */,
130 | E852EBB81973570100DC53E7 /* Resources */,
131 | );
132 | buildRules = (
133 | );
134 | dependencies = (
135 | );
136 | name = Todo;
137 | productName = Todo;
138 | productReference = E852EBBA1973570100DC53E7 /* Todo.app */;
139 | productType = "com.apple.product-type.application";
140 | };
141 | E852EBCB1973570100DC53E7 /* TodoTests */ = {
142 | isa = PBXNativeTarget;
143 | buildConfigurationList = E852EBD91973570100DC53E7 /* Build configuration list for PBXNativeTarget "TodoTests" */;
144 | buildPhases = (
145 | E852EBC81973570100DC53E7 /* Sources */,
146 | E852EBC91973570100DC53E7 /* Frameworks */,
147 | E852EBCA1973570100DC53E7 /* Resources */,
148 | );
149 | buildRules = (
150 | );
151 | dependencies = (
152 | E852EBCE1973570100DC53E7 /* PBXTargetDependency */,
153 | );
154 | name = TodoTests;
155 | productName = TodoTests;
156 | productReference = E852EBCC1973570100DC53E7 /* TodoTests.xctest */;
157 | productType = "com.apple.product-type.bundle.unit-test";
158 | };
159 | /* End PBXNativeTarget section */
160 |
161 | /* Begin PBXProject section */
162 | E852EBB21973570100DC53E7 /* Project object */ = {
163 | isa = PBXProject;
164 | attributes = {
165 | LastSwiftMigration = 0720;
166 | LastSwiftUpdateCheck = 0720;
167 | LastUpgradeCheck = 0720;
168 | ORGANIZATIONNAME = "Marcus Molchany";
169 | TargetAttributes = {
170 | E852EBB91973570100DC53E7 = {
171 | CreatedOnToolsVersion = 6.0;
172 | DevelopmentTeam = XJR9Z8H52H;
173 | };
174 | E852EBCB1973570100DC53E7 = {
175 | CreatedOnToolsVersion = 6.0;
176 | TestTargetID = E852EBB91973570100DC53E7;
177 | };
178 | };
179 | };
180 | buildConfigurationList = E852EBB51973570100DC53E7 /* Build configuration list for PBXProject "Todo" */;
181 | compatibilityVersion = "Xcode 3.2";
182 | developmentRegion = English;
183 | hasScannedForEncodings = 0;
184 | knownRegions = (
185 | en,
186 | Base,
187 | );
188 | mainGroup = E852EBB11973570100DC53E7;
189 | productRefGroup = E852EBBB1973570100DC53E7 /* Products */;
190 | projectDirPath = "";
191 | projectRoot = "";
192 | targets = (
193 | E852EBB91973570100DC53E7 /* Todo */,
194 | E852EBCB1973570100DC53E7 /* TodoTests */,
195 | );
196 | };
197 | /* End PBXProject section */
198 |
199 | /* Begin PBXResourcesBuildPhase section */
200 | E852EBB81973570100DC53E7 /* Resources */ = {
201 | isa = PBXResourcesBuildPhase;
202 | buildActionMask = 2147483647;
203 | files = (
204 | E852EBC51973570100DC53E7 /* Main.storyboard in Resources */,
205 | E852EBC71973570100DC53E7 /* Images.xcassets in Resources */,
206 | );
207 | runOnlyForDeploymentPostprocessing = 0;
208 | };
209 | E852EBCA1973570100DC53E7 /* Resources */ = {
210 | isa = PBXResourcesBuildPhase;
211 | buildActionMask = 2147483647;
212 | files = (
213 | );
214 | runOnlyForDeploymentPostprocessing = 0;
215 | };
216 | /* End PBXResourcesBuildPhase section */
217 |
218 | /* Begin PBXSourcesBuildPhase section */
219 | E852EBB61973570100DC53E7 /* Sources */ = {
220 | isa = PBXSourcesBuildPhase;
221 | buildActionMask = 2147483647;
222 | files = (
223 | E852EBC21973570100DC53E7 /* ViewController.swift in Sources */,
224 | E852EBDD1973718800DC53E7 /* AddTodoItemViewController.swift in Sources */,
225 | E87E98B21974B478000C2B39 /* TodoItem.swift in Sources */,
226 | E852EBDF197373E700DC53E7 /* TodoListTableTableViewController.swift in Sources */,
227 | E852EBC01973570100DC53E7 /* AppDelegate.swift in Sources */,
228 | );
229 | runOnlyForDeploymentPostprocessing = 0;
230 | };
231 | E852EBC81973570100DC53E7 /* Sources */ = {
232 | isa = PBXSourcesBuildPhase;
233 | buildActionMask = 2147483647;
234 | files = (
235 | E852EBD31973570100DC53E7 /* TodoTests.swift in Sources */,
236 | );
237 | runOnlyForDeploymentPostprocessing = 0;
238 | };
239 | /* End PBXSourcesBuildPhase section */
240 |
241 | /* Begin PBXTargetDependency section */
242 | E852EBCE1973570100DC53E7 /* PBXTargetDependency */ = {
243 | isa = PBXTargetDependency;
244 | target = E852EBB91973570100DC53E7 /* Todo */;
245 | targetProxy = E852EBCD1973570100DC53E7 /* PBXContainerItemProxy */;
246 | };
247 | /* End PBXTargetDependency section */
248 |
249 | /* Begin PBXVariantGroup section */
250 | E852EBC31973570100DC53E7 /* Main.storyboard */ = {
251 | isa = PBXVariantGroup;
252 | children = (
253 | E852EBC41973570100DC53E7 /* Base */,
254 | );
255 | name = Main.storyboard;
256 | sourceTree = "";
257 | };
258 | /* End PBXVariantGroup section */
259 |
260 | /* Begin XCBuildConfiguration section */
261 | E852EBD41973570100DC53E7 /* Debug */ = {
262 | isa = XCBuildConfiguration;
263 | buildSettings = {
264 | ALWAYS_SEARCH_USER_PATHS = NO;
265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
266 | CLANG_CXX_LIBRARY = "libc++";
267 | CLANG_ENABLE_MODULES = YES;
268 | CLANG_ENABLE_OBJC_ARC = YES;
269 | CLANG_WARN_BOOL_CONVERSION = YES;
270 | CLANG_WARN_CONSTANT_CONVERSION = YES;
271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
272 | CLANG_WARN_EMPTY_BODY = YES;
273 | CLANG_WARN_ENUM_CONVERSION = YES;
274 | CLANG_WARN_INT_CONVERSION = YES;
275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
276 | CLANG_WARN_UNREACHABLE_CODE = YES;
277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
278 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
279 | COPY_PHASE_STRIP = NO;
280 | ENABLE_STRICT_OBJC_MSGSEND = YES;
281 | ENABLE_TESTABILITY = YES;
282 | GCC_C_LANGUAGE_STANDARD = gnu99;
283 | GCC_DYNAMIC_NO_PIC = NO;
284 | GCC_OPTIMIZATION_LEVEL = 0;
285 | GCC_PREPROCESSOR_DEFINITIONS = (
286 | "DEBUG=1",
287 | "$(inherited)",
288 | );
289 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
292 | GCC_WARN_UNDECLARED_SELECTOR = YES;
293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
294 | GCC_WARN_UNUSED_FUNCTION = YES;
295 | GCC_WARN_UNUSED_VARIABLE = YES;
296 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
297 | MTL_ENABLE_DEBUG_INFO = YES;
298 | ONLY_ACTIVE_ARCH = YES;
299 | SDKROOT = iphoneos;
300 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
301 | };
302 | name = Debug;
303 | };
304 | E852EBD51973570100DC53E7 /* Release */ = {
305 | isa = XCBuildConfiguration;
306 | buildSettings = {
307 | ALWAYS_SEARCH_USER_PATHS = NO;
308 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
309 | CLANG_CXX_LIBRARY = "libc++";
310 | CLANG_ENABLE_MODULES = YES;
311 | CLANG_ENABLE_OBJC_ARC = YES;
312 | CLANG_WARN_BOOL_CONVERSION = YES;
313 | CLANG_WARN_CONSTANT_CONVERSION = YES;
314 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
315 | CLANG_WARN_EMPTY_BODY = YES;
316 | CLANG_WARN_ENUM_CONVERSION = YES;
317 | CLANG_WARN_INT_CONVERSION = YES;
318 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
319 | CLANG_WARN_UNREACHABLE_CODE = YES;
320 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
321 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
322 | COPY_PHASE_STRIP = YES;
323 | ENABLE_NS_ASSERTIONS = NO;
324 | ENABLE_STRICT_OBJC_MSGSEND = YES;
325 | GCC_C_LANGUAGE_STANDARD = gnu99;
326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
328 | GCC_WARN_UNDECLARED_SELECTOR = YES;
329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
330 | GCC_WARN_UNUSED_FUNCTION = YES;
331 | GCC_WARN_UNUSED_VARIABLE = YES;
332 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
333 | MTL_ENABLE_DEBUG_INFO = NO;
334 | SDKROOT = iphoneos;
335 | VALIDATE_PRODUCT = YES;
336 | };
337 | name = Release;
338 | };
339 | E852EBD71973570100DC53E7 /* Debug */ = {
340 | isa = XCBuildConfiguration;
341 | buildSettings = {
342 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
343 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
344 | CODE_SIGN_IDENTITY = "iPhone Developer";
345 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
346 | INFOPLIST_FILE = Todo/Info.plist;
347 | IPHONEOS_DEPLOYMENT_TARGET = 9.2;
348 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
349 | PRODUCT_BUNDLE_IDENTIFIER = jdk.Todo;
350 | PRODUCT_NAME = "$(TARGET_NAME)";
351 | PROVISIONING_PROFILE = "";
352 | TARGETED_DEVICE_FAMILY = 1;
353 | };
354 | name = Debug;
355 | };
356 | E852EBD81973570100DC53E7 /* Release */ = {
357 | isa = XCBuildConfiguration;
358 | buildSettings = {
359 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
360 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
361 | CODE_SIGN_IDENTITY = "iPhone Developer";
362 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
363 | INFOPLIST_FILE = Todo/Info.plist;
364 | IPHONEOS_DEPLOYMENT_TARGET = 9.2;
365 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
366 | PRODUCT_BUNDLE_IDENTIFIER = jdk.Todo;
367 | PRODUCT_NAME = "$(TARGET_NAME)";
368 | PROVISIONING_PROFILE = "";
369 | TARGETED_DEVICE_FAMILY = 1;
370 | };
371 | name = Release;
372 | };
373 | E852EBDA1973570100DC53E7 /* Debug */ = {
374 | isa = XCBuildConfiguration;
375 | buildSettings = {
376 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Todo.app/Todo";
377 | FRAMEWORK_SEARCH_PATHS = (
378 | "$(SDKROOT)/Developer/Library/Frameworks",
379 | "$(inherited)",
380 | );
381 | GCC_PREPROCESSOR_DEFINITIONS = (
382 | "DEBUG=1",
383 | "$(inherited)",
384 | );
385 | INFOPLIST_FILE = TodoTests/Info.plist;
386 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
387 | PRODUCT_BUNDLE_IDENTIFIER = "self.${PRODUCT_NAME:rfc1034identifier}";
388 | PRODUCT_NAME = "$(TARGET_NAME)";
389 | TEST_HOST = "$(BUNDLE_LOADER)";
390 | };
391 | name = Debug;
392 | };
393 | E852EBDB1973570100DC53E7 /* Release */ = {
394 | isa = XCBuildConfiguration;
395 | buildSettings = {
396 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Todo.app/Todo";
397 | FRAMEWORK_SEARCH_PATHS = (
398 | "$(SDKROOT)/Developer/Library/Frameworks",
399 | "$(inherited)",
400 | );
401 | INFOPLIST_FILE = TodoTests/Info.plist;
402 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
403 | PRODUCT_BUNDLE_IDENTIFIER = "self.${PRODUCT_NAME:rfc1034identifier}";
404 | PRODUCT_NAME = "$(TARGET_NAME)";
405 | TEST_HOST = "$(BUNDLE_LOADER)";
406 | };
407 | name = Release;
408 | };
409 | /* End XCBuildConfiguration section */
410 |
411 | /* Begin XCConfigurationList section */
412 | E852EBB51973570100DC53E7 /* Build configuration list for PBXProject "Todo" */ = {
413 | isa = XCConfigurationList;
414 | buildConfigurations = (
415 | E852EBD41973570100DC53E7 /* Debug */,
416 | E852EBD51973570100DC53E7 /* Release */,
417 | );
418 | defaultConfigurationIsVisible = 0;
419 | defaultConfigurationName = Release;
420 | };
421 | E852EBD61973570100DC53E7 /* Build configuration list for PBXNativeTarget "Todo" */ = {
422 | isa = XCConfigurationList;
423 | buildConfigurations = (
424 | E852EBD71973570100DC53E7 /* Debug */,
425 | E852EBD81973570100DC53E7 /* Release */,
426 | );
427 | defaultConfigurationIsVisible = 0;
428 | defaultConfigurationName = Release;
429 | };
430 | E852EBD91973570100DC53E7 /* Build configuration list for PBXNativeTarget "TodoTests" */ = {
431 | isa = XCConfigurationList;
432 | buildConfigurations = (
433 | E852EBDA1973570100DC53E7 /* Debug */,
434 | E852EBDB1973570100DC53E7 /* Release */,
435 | );
436 | defaultConfigurationIsVisible = 0;
437 | defaultConfigurationName = Release;
438 | };
439 | /* End XCConfigurationList section */
440 | };
441 | rootObject = E852EBB21973570100DC53E7 /* Project object */;
442 | }
443 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Swift TODO App Tutorial
2 |
3 | _Note:_ This repo is fairly out of date. Use at your own risk.
4 |
5 | CODE version: xCode 7.2.1, Swift 2.0
6 |
7 | README version: xCode 6.0, Swift 1.0
8 |
9 | =======================
10 |
11 | - [Foreword](#user-content-foreword)
12 | - [Installing This App](#user-content-installing-this-app)
13 | - [Feedback](#user-content-feedback)
14 | - [Getting Start: The Basics](#user-content-getting-start-the-basics)
15 | - [Create your project](#user-content-create-your-project)
16 | - [Add a textfield to your storyboard](#user-content-add-a-textfield-to-your-storyboard)
17 | - [Gluing Our Views Together: The storyboard](#user-content-gluing-our-views-together-the-storyboard)
18 | - [Position text field using Auto Layout](#user-content-position-text-field-using-auto-layout)
19 | - [Create a table view controller](#user-content-create-a-table-view-controller)
20 | - [Add a segue to navigate forward](#user-content-add-a-segue-to-navigate-forward)
21 | - [Configure the Add button](#user-content-configure-the-add-button)
22 | - [Add a navigation controller to the view controller](#user-content-add-a-navigation-controller-to-the-view-controller)
23 | - [Finally Programming: Swift](#user-content-finally-programming-swift)
24 | - [Create a custom view controller that is a subclass of UIViewController](#user-content-create-a-custom-view-controller-that-is-a-subclass-of-uiviewcontroller)
25 | - [Create a custom table view controller that is a subclass of UITableViewController](#user-content-create-a-custom-table-view-controller-that-is-a-subclass-of-uitableviewcontroller)
26 | - [Connecting cancel and done buttons to exit segue](#user-content-connecting-cancel-and-done-buttons-to-exit-segue)
27 | - [Create a Data Class](#user-content-create-a-data-class)
28 | - [Fill in your TodoItem class](#user-content-fill-in-your-todoitem-class)
29 | - [Give your table view controller an array of TodoItems](#user-content-give-your-table-view-controller-an-array-of-todoitems)
30 | - [Mark item as complete](#user-content-mark-item-as-complete)
31 | - [Lastly - add new items](#user-content-lastly---add-new-items)
32 |
33 | ## Foreword
34 |
35 | 1. This tutorial is based on [Apple's xCode 5 Objective C TODO tutorial](https://developer.apple.com/library/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html#//apple_ref/doc/uid/TP40011343-CH2-SW1), which is an excellent place to look for auxiliary context (and screenshots!)
36 | 1. Check out the Todo folder for the completed code
37 |
38 | ## Installing This App
39 |
40 | 1. `cd /your/preferred/xcode/location`
41 | 1. `git clone https://github.com/jadekler/git-swift-todo-tutorial.git`
42 | 1. Open xcode
43 | 1. File > Open > /your/preferred/xcode/location/git-swift-todo-tutorial/Todo/Todo.xcodeproj
44 |
45 | ## Feedback
46 |
47 | Please, provide feedback on anything you feel is lacking or could be better worded! Pull requests, github issues, or direct emails to jadekler@gmail.com are all welcome!
48 |
49 | ## Getting Start: The Basics
50 |
51 | ##### Create your project
52 | 1. Open xCode
53 | 1. Under iOS > Application, select 'Single View Application' and click Next
54 | 1. Enter as follows 
55 | 1. Checkpoint: Hit the run button on the top left of xCode - you should see a blank white screen
56 |
57 | ##### Add a textfield to your storyboard
58 | 1. In the Project Navigator on the far left of xCode, select Main.storyboard
59 | 1. Find the Object Library, and find or search for 'Text Field'
60 | 1.
61 | 1. Drag one to the furthest left guider on your View, about 1/3 from the top of your view
62 | 1. Increase the width of the text field by dragging the right side of the text view to the rightmost guider
63 | 1. Next, let's change the placeholder text
64 | 1. In the Utilities Slider on the right side of Xcode, find the Attributes Inspector (4th icon on the top bar from the left)
65 | 1. Enter 'new todo' next to 'Placeholder'
66 | 1. Your storyboard should look like this: 
67 | 1. Checkpoint: Hit the run button on the top left of xCode - you should see a blank white screen with a text field that says 'New Todo' (don't worry if the text field goes off of the screen)
68 |
69 | ## Gluing Our Views Together: The storyboard
70 |
71 | ##### Position text field using Auto Layout
72 | When you run your code, you can change orientation by going to 'Hardware' and clicking one of the rotate buttons. Note that when you do so, your text field doesn't adjust its size automatically. Let's address that.
73 |
74 | 1. In the Project Navigator on the far left of xCode, select Main.storyboard
75 | 1. Click on the Text Field in the View
76 | 1. Set top space on the top
77 | 1. Control+Click and Drag from the Text Field to the area right above, which should highlight blue and say 'View'
78 | 1. Release your drag
79 | 1. Select 'Top Space to Top Layout Guide' from the small black menu
80 | 1. Set leading space on the left
81 | 1. Control+Click and Drag from the Text Field to the area left of the view, which should highlight blue and say 'View'
82 | 1. Release your drag
83 | 1. Select 'Leading Space to Container Margin' from the small black menu
84 | 1. Set Trailing space on the right
85 | 1. Control+Click and Drag from the Text Field to the area right of the view, which should highlight blue and say 'View'
86 | 1. Release your drag
87 | 1. Select 'Trailing Space to Container Margin' from the small black menu
88 | 1. Checkpoint: Hit the run button on the top left of xCode
89 | 1. You should see the Text Field with equal spacing on each side and spacing from the top bar
90 | 1. On the top bar of your computer click 'Hardware' and click 'Rotate Left' to enter landscape view
91 | 1. The left, right, and top margin should match the portrait view
92 |
93 | ##### Create a table view controller
94 | 1. In the Project Navigator on the far left of xCode, select Main.storyboard
95 | 1. In the Object Library, search for table view controller
96 | 1. Drag a table view controller and drop it into the canvas. If you're lacking in space, right click on the canvas to zoom out
97 |
98 |
99 | 1. Click the arrow on the left of your view controller
100 | 1. Drag and drop it on your table view controller to set the table view controller as the initial scene
101 | 1. Your canvas should now look like this: 
102 | 1. Checkpoint: Hit the run button on the top left of xCode - you should see an empty table view
103 |
104 | ##### Add a segue to navigate forward
105 | 1. Select your Table View Controller
106 | 1. With the view controller selected, choose Editor > Embed In > Navigation Controller
107 | 1. In the canvas, select the newly created title area on your table view (or in the outline view select Navigation Item under Table View Controller)
108 | 1. 
109 | 1. In the Attributes inspector, type 'My To-Do List' in the Title field
110 | 1. Add a '+' button
111 | 1. Drag a Bar Button Item object from the Object Library to the far right of the navigation bar in the table view controller
112 | 1. Select the newly created bar button item
113 | 1. In the Attributes Inspector, change the Identifier from Custom to Add
114 | 1. Checkpoint: Hit the run button on the top left of xCode - you should see your newly created + button, but it won't do anything just yet
115 |
116 | ##### Configure the Add button
117 | 1. Control+Click and Drag from the Add button to your original View Controller
118 | 1. Release the drag and select 'present modally'
119 | 1. Checkpoint: Hit the run button on the top left of xCode - Click the + button and the New Todo view should appear
120 |
121 | ##### Add a navigation controller to the view controller
122 | 1. Select your view controller
123 |
124 | 1. With the view controller selected, choose Editor > Embed In > Navigation Controller
125 | 1. In the canvas, select the newly created title area on your table view (or in the outline view select Navigation Item under Table View Controller)
126 | 1. In the Attributes inspector, type 'Add Todo' in the Title field
127 | 1. Add a 'Done' button right to the title
128 | 1. Drag a Bar Button Item object from the Object Library to the far right of the navigation bar in the table view controller
129 | 1. Select the newly created bar button item
130 | 1. In the Attributes inspector, find the Identifier option in the Bar Button Item section. Choose 'Done' from the Identifier pop-up menu
131 | 1. Add a 'Cancel' button to the left of the title
132 | 1. Drag a Bar Button Item object from the Object Library to the far right of the navigation bar in the table view controller
133 | 1. Select the newly created bar button item
134 | 1. In the Attributes inspector, find the Identifier option in the Bar Button Item section. Choose 'Cancel' from the Identifier pop-up menu
135 | 1. 
136 | 1. Checkpoint: Hit the run button on the top left of xCode - you should see your newly created 'Done' and 'Cancel' buttons when you navigate to 'Add a todo', but they won't do anything just yet
137 |
138 | ## Finally Programming: Swift
139 |
140 | ##### Create a custom view controller that is a subclass of UIViewController
141 | 1. Choose File > New > File (or press Command-N)
142 | 1. Fill in as follows 
143 | 1. Click Next, and Create
144 | 1. The Targets section will default to having your app selected and the tests for your app unselected. That’s perfect, so leave that as is
145 | 1. Click Create
146 |
147 | Now that you’ve created a custom view controller subclass, you need to tell your storyboard to use your custom class instead of the generic view controller.
148 |
149 | 1. In the project navigator, select Main.storyboard
150 | 1. Select your View Controller (in the Outline View, this is 'View Controller' under the 'Add a todo Scene')
151 | 1. In the Identity inspector, open the pop-up menu next to the Class option
152 | 1. Choose AddToDoItemViewController
153 |
154 | ##### Create a custom table view controller that is a subclass of UITableViewController
155 | 1. Choose File > New > File (or press Command-N)
156 | 1. On the left of the dialog that appears, select the Cocoa Touch Class under iOS
157 | 1. 
158 | 1. Click Next
159 | 1. Click Next, and Create
160 | 1. The Targets section will default to having your app selected and the tests for your app unselected. That’s perfect, so leave that as is
161 | 1. In the project navigator, select Main.storyboard
162 | 1. Select your **Table** View Controller (in the Outline View, this is 'Table View Controller' under the 'Todo list Scene')
163 | 1. In the Identity inspector, open the pop-up menu next to the Class option
164 | 1. Choose ToDoListTableViewController
165 |
166 | ##### Connecting cancel and done buttons to exit segue
167 |
168 | 1. Navigate to your TodoListTableTableViewController.swift
169 | 1. Add the following function (this registers the action and allows it to be used in storyboard):
170 | ```swift
171 | @IBAction func unwindToList(segue: UIStoryboardSegue) {
172 | println("Unwinding")
173 | }
174 |
175 | ```
176 | 1. Navigate to your storyboard
177 | 1. On the canvas, Control-drag from the 'Cancel' button to the Exit item right above (the right item of the three squares above )
178 | 1. Choose unwindToList: from the shortcut menu
179 | 1. Do the same for the 'Done' button
180 | 1. Checkpoint: Hit the run button on the top left of xCode - when you navigate over to Add a todo, your cancel and done buttons should pop you back over to Todo list (your table view)
181 |
182 | ##### Create a Data Class
183 | 1. Choose File > New > File
184 | 1. Select Cocoa Touch Class and click Next
185 | 1. Fill in as follows 
186 | 1. Click Next, and Create
187 | Your class should look like this
188 | ```swift
189 | import UIKit
190 |
191 | class ToDoItem: NSObject {
192 |
193 | }
194 | ```
195 |
196 | ##### Fill in your TodoItem class
197 | 1. Give it a name and completed variable and initialize them like so:
198 | ```swift
199 | import UIKit
200 |
201 | class TodoItem: NSObject {
202 | let itemName: String
203 | var completed: Bool
204 |
205 | init(itemName: String, completed: Bool = false) {
206 | self.itemName = itemName
207 | self.completed = completed
208 | }
209 | }
210 | ```
211 |
212 | ##### Give your table view controller an array of TodoItems
213 | 1. Navigate to TodoTableListViewController.swift
214 | 1. Give it an array of TodoItems:
215 | ```
216 | var todoItems: [TodoItem] = []
217 |
218 | ```
219 | 1. Give it a loadInitialData function that populates your array with some basic things:
220 | ```swift
221 | func loadInitialData() {
222 | todoItems = [
223 | TodoItem(itemName: "Go to the dentist"),
224 | TodoItem(itemName: "Fetch groceries"),
225 | TodoItem(itemName: "Sleep")
226 | ]
227 | }
228 |
229 | ```
230 | 1. Load your initial data from the viewDidLoad function:
231 | ```swift
232 | override func viewDidLoad() {
233 | super.viewDidLoad()
234 | loadInitialData()
235 | }
236 |
237 | ```
238 | 1. Make the number of sections in your table one:
239 | ```swift
240 | override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
241 | return 1
242 | }
243 |
244 | ```
245 | 1. Next, let's create a function that returns the number of rows per section. Since we only have one section, we'll return a count of the todoItems. Add the following function:
246 | ```swift
247 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
248 | return todoItems.count
249 | }
250 |
251 | ```
252 |
253 | 1. The last function we need will generate UITableViewCells for each row at a specific index
254 | ```swift
255 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
256 | let tempCell = tableView.dequeueReusableCellWithIdentifier("ListPrototypeCell") as UITableViewCell
257 | let todoItem = todoItems[indexPath.row]
258 |
259 | // Downcast from UILabel? to UILabel
260 | let cell = tempCell.textLabel as UILabel!
261 | cell.text = todoItem.itemName
262 |
263 | return tempCell
264 | }
265 | ```
266 | 1. In the project navigator select Main.storyboard
267 | 1. In the Todo list TableView select the Prototype Table View Cell
268 | 1. In the Utilities slider on the right, go to the Attributes Inspector (4th icon from the left)
269 | 1. For the Identifier change to ListPrototypeCell
270 | 1. See: 
271 | 1. Checkpoint - Run the app, the Table View should populate with the initial data "Go to the dentist", "Fetch groceries", "Sleep"
272 |
273 | ##### Mark item as complete
274 | 1. In the project navigator select TodoListTableViewController.swift
275 | 1. Add a tableView on select function to mark todoItems as complete
276 | ```swift
277 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
278 | tableView.deselectRowAtIndexPath(indexPath, animated: false)
279 |
280 | let tappedItem = todoItems[indexPath.row] as TodoItem
281 | tappedItem.completed = !tappedItem.completed
282 |
283 | tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
284 | }
285 | ```
286 | 1. Modify the tableView cell display function to have a checkmark if the item is finished
287 |
288 | ```swift
289 | if (todoItem.completed) {
290 | tempCell.accessoryType = UITableViewCellAccessoryType.Checkmark;
291 | } else {
292 | tempCell.accessoryType = UITableViewCellAccessoryType.None;
293 | }
294 | ```
295 | 1. The final version:
296 | ```swift
297 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
298 | let tempCell = tableView.dequeueReusableCellWithIdentifier("ListPrototypeCell") as UITableViewCell
299 | let todoItem = todoItems[indexPath.row]
300 |
301 | // Downcast from UILabel? to UILabel
302 | let cell = tempCell.textLabel as UILabel!
303 | cell.text = todoItem.itemName
304 |
305 | if (todoItem.completed) {
306 | tempCell.accessoryType = UITableViewCellAccessoryType.Checkmark;
307 | } else {
308 | tempCell.accessoryType = UITableViewCellAccessoryType.None;
309 | }
310 |
311 | return tempCell
312 | }
313 | ```
314 | 1. Checkpoint - run the app, click an item and a check mark should appear next to it, click it again to make the checkmark disappear
315 |
316 | ##### Lastly - add new items
317 | 1. In the project navigator select Main.storyboard
318 | 1. In the outline view, select the AddTodoItemViewController object
319 | 1. Click the Assistant button in the upper right of the window’s toolbar to open the assistant editor (the suit-looking icon)
320 | 1. The editor on the right should appear with AddTodoItemViewController.swift displayed. If it isn’t displayed, click the filename in the editor on the right and choose AddTodoItemViewController.swift
321 | 1. Select the text field in your storyboard
322 | 1. 
323 | 1. Control-drag from the text field on your canvas to the code display in the editor on the right, somewhere inside the class, and type textField for name
324 | 1. Click Connect. This should add the following to your code: ```@IBOutlet weak var textField: UITextField!```
325 | 1. Do the same for the Done button, calling it 'doneButton'. In your code it should look like ```@IBOutlet weak var doneButton: UIBarButtonItem!```
326 | 1. Next, let's give our controller a todoItem that it will store our 'add' data into: ```var todoItem: TodoItem = TodoItem(itemName: "")```
327 | 1. Of course we also need to be able to take data from the user input and assign it to this variable:
328 |
329 | ```swift
330 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
331 | if (countElements(self.textField.text) > 0) {
332 | self.todoItem = TodoItem(itemName: self.textField.text)
333 | }
334 | }
335 | ```
336 | 1. Now, we need to head back over to TodoListTableTableViewController.swift and add an unwind that takes the data that AddTodoItemViewController.swift is holding and pops into the array of todoItems:
337 | ```swift
338 | @IBAction func unwindAndAddToList(segue: UIStoryboardSegue) {
339 | let source = segue.sourceViewController as AddTodoItemViewController
340 | let todoItem:TodoItem = source.todoItem
341 |
342 | if todoItem.itemName != "" {
343 | self.todoItems.append(todoItem)
344 | self.tableView.reloadData()
345 | }
346 | }
347 | ```
348 | 1. Lastly, select Main.storyboard in the project navigator
349 | 1. On the canvas, Control-drag from the 'Done' button to the Exit item and select unwindAndAddToList
350 | 1. Checkpoint: Run your app - you should be able to add items!
351 |
352 | ## That's it!
353 | As mentioned before, we love feedback - please open issues about anything you feel is missing, or email the authors directly about questions or feedback at jadekler@gmail.com.
354 |
355 | [1]: http://stackoverflow.com/questions/24029586/xcode-6-storyboard-unwind-segue-with-swift-not-connecting-to-exit
356 |
--------------------------------------------------------------------------------