├── .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 ![](/img/img_1.png) 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: ![](/img/img_3.png) 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: ![](/img/img_4.png) 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. ![](/img/img_5.png) 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. ![](/img/img_6.png) 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 ![](/img/img_7.png) 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. ![](/img/img_8.png) 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 ![](/img/img_9.png) 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: ![](/img/img_10.png) 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. ![](/img/img_11.png) 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 | --------------------------------------------------------------------------------