Creating a Task Application for iOS using Swift

In this tutorial, I’ll walk you through building a tasks application for iOS using Swift. This app will allow you to quickly enter and delete tasks like going to the grocery store, etc. It will also lay the foundation needed in order to build native apps with Swift in the future.

In order to get started, you will need to download Xcode 6 from the AppStore. It is free and will allow you to follow along with this tutorial. You will also need at least Mac OS X 10.9.3 to run Xcode 6.

Please note that this tutorial was written with Xcode 6.1.1, which contains the latest improvements to the Swift language.

Let’s Get Started

Launch Xcode and create a new Project. Use the “Tabbed Application” template and press Next.

templates

By choosing the “Tabbed Application” template, we now have a project that uses the tab bar. It provides a user interface configured with a tab bar controller, and view controllers for the tab bar items.

Enter a name for your application and make sure the language of choice is Swift and iPhone is the target device.

Taking a Look at the Project Structure

Once the project finishes loading, if you look on the left-hand side of your screen, you will see the following:

structure

A quick break down of each file is:

  • AppDelegate.swift – Is the App’s main entry point.
  • FirstViewController.swift – Controls the first tab and is where we will display the current tasks.
  • SecondViewController.swift – Controls the second tab and is where we will add tasks.
  • Main.storyboard – Is where we will add UI components and visualize our app.
  • Images.xcassets – contains icons or any images needed for the app.
  • LaunchScreen.xib – Is a splash screen that is recommended to use for iPhone 6 and 6 Plus.

Digging Deeper

We will begin by adding a new file to the project. We will choose the template called, “Cocoa Touch Class” and give it the name of TaskManager.

Inside TaskManager.swift add the following code:

import UIKit

var taskMgr: TaskManager = TaskManager()

struct task {
    var name = "Name"
    var desc = "Description"
}

class TaskManager: NSObject {
    var tasks = [task]()

    func addTask(name: String, desc: String){
        tasks.append(task(name: name, desc: desc))
    }
}

Since we are going to need access to this class throughout our application (in both of the views), we can declare a taskMgr variable and instantiate this class. We then setup a struct with two properties that will collect the data from our text fields we are about to setup in our Main.storyboard. Finally, we’ve added an array that will store the task name and description to make it easier to work with the entered data later in a tableview.

Defining our UI

Switch over to the Main.storyboard file and you will see the following:

storyboard

For the First View (List tasks to be completed)

  • Remove the two labels (Simply select them and press delete)
  • Add a TableView from the Object Library and make sure it fits the screen leaving the carrier information available.
  • While TableView is still highlighted click on the connection inspector and drag and drop both the dataSouce and the delegate to the Task View Controller as shown below :

tableview

  • Click on the “First” icon and click the attributes inspector and change the title to “Tasks”.
  • Since we want this application to look great on all versions of the iPhone (like the 6 and 6 plus), we will need to click on “Resolve Auto Layout Issue” at the bottom of our view and click on “Add Missing Constaints”. Please note that sometimes “Add Missing Constraints” doesn’t always fix your issues, especially on older devices like the iPhone 4S. For future info, check out Xcode’s Help Documentation.

For the Second View (Gather tasks from the user)

  • Remove the two labels (simply select them and press delete)
  • Add a Label to the top and change the text to “Add Task” again making sure it fits the screen leaving the carrier info available.
  • Add Two Text Fields and center them under the label and change the placeholder text for the first one to “Name” and the second one to “Description”.
  • Add a Button below the second text field and change the text to say, “Save”.
  • Click on the “Second” icon and click the attributes inspector and change the title to “Add Tasks”.
  • Click on the Text Field and click on the connection inspector and drag and drop the delegate to the Add Task View Controller as shown below :

textfielddelegate

  • Again, we will need to click on “Resolve Auto Layout Issue” and click on “Add Missing Constaints”.

Before Moving On

If you noticed the icons on the “Tasks” and “Add Tasks” buttons, then you probably realized that they don’t have any meaning to the user as they are a circle and a square. What I typically do in instances like this are search for free-to-use commercial icons like the ones from icons8. After searching I found a “Create New” icon that I could use for the “Add Tasks” button.

The second icon I used was for the list.


All you have to do is simply place the images in the Images.xcassets folder and make sure the image of each tab strip button is set to the proper image.

Our UI

Your completed storyboard should look like the following:

firstview

Time to write some code!

FirstViewController.swift

We need to extend our class to include the necessary protocols required to use the TableView. You can do that by adding UITableViewDelegate and UITableViewDataSource to the class as shown below:

class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource

You should see red squiggly lines now – don’t worry as we will implement the methods shortly.

We need to declare an outlet for our TableView where we can perform tasks on it later.

@IBOutlet var tblTasks : UITableView!

Switch back to Main.storyboard, making sure the TableView is selected, click on the “Connection Inspector” and verify that the Referencing Outlets is mapped to the Tasks View Controller as shown below:

tableviewoutlet

You can simpy drag and drop tblTasks to the FirstViewController like we did earlier for the dataSource and delegate.

We are going to add one line to the viewDidLoad method to reload the table data upon each load of this view.

override func viewDidLoad() {
    super.viewDidLoad()
    tblTasks.reloadData()
}

Now we must add a function that will return the number of rows to the TableView. This information will come directly from the array that we created earlier. Thankfully, arrays have a property called count that we will use to return the number of rows to be displayed.

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    return taskMgr.tasks.count
}

We also need to display data inside of the cells. We are simply going to pull the data out of the array that has been created and put the Task Name and Description into a cell for each item found.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
    let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Default Tasks")

    cell.textLabel?.text = taskMgr.tasks[indexPath.row].name
    cell.detailTextLabel?.text = taskMgr.tasks[indexPath.row].desc

    return cell
}

If a user swipes on a cell from the left, we want to show the “Delete” button and remove the item from the array as well as update our TableView.

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
    if (editingStyle == UITableViewCellEditingStyle.Delete){

        taskMgr.tasks.removeAtIndex(indexPath.row)
        tblTasks.reloadData()
    }
}

SecondViewController.swift

We’ll begin by extending our class to include the protocol necessary to facilitate working with the TextField. You can do that by adding UITextFieldDelegate to the class as shown below :

class SecondViewController: UIViewController, UITextFieldDelegate

Again, we are going to add two outlets for each of the text fields that we added earlier.

@IBOutlet var txtTask: UITextField!
@IBOutlet var txtDesc: UITextField!

Switch back to Main.storyboard and for each TextField click on the “Connection Inspector” and make sure that the Referencing Outlets for each TextField is mapped to the appropriate outlet as shown below:

textfieldoutlet

We are going to add an action for our button. First, add the following code to SecondViewController.swift:

@IBAction func btnAddTask(sender : UIButton){
    if (txtTask.text == ""){
        //Task Title is blank, do not add a record
    } else {
    //add record
    taskMgr.addTask(txtTask.text, desc: txtDesc.text)

    //dismiss keyboard and reset fields

    self.view.endEditing(true)
    txtTask.text = nil
    txtDesc.text = nil

    }
}

Next, switch back to Main.storyboard and for the button click on the “Connection Inspector” and make sure that the “Touch Up Inside ” is mapped to the btnAddTask as shown below.

buttontouch

This code will simply check and make sure something was entered in the Title field before adding the data to our array. We’ll make it optional to add a description.

The last two functions in SecondViewController.swift will simply dismiss the keyboard when the user touches on the screen as well as when they press the return key.

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    self.view.endEditing(true)
}

func textFieldShouldReturn(textField: UITextField) -> Bool{
    textField.resignFirstResponder()
    return true
}

If you did everything correctly, then select iPhone 6 as your simulator and hit the run button. Your app should look like the following:

demo

Note: The full source for the demo can be found on Github. If you would like a more detailed example using Core Data to persist the items and other cosmetic tweaks, then check out my repo here.

Winding Down

Today we learned how to use Apple’s new programming language called Swift to write a task app that runs on the iPhone. With Swift recently being released, this should help you on your journey to writing a native iOS App using the language that Apple is fully invested in. I’d encourage you to take this app and either extend it or build another app using the techniques you learned today. I’ve included some additional resources found below:

Header image courtesy of Cliff Johnson

Comments

  • Pingback: Dew Drop – January 26, 2015 (#1940) | Morning Dew()

  • James Hartley

    The data doesn’t save after the app is fully restarted. Anyway to correct for this?

  • Pingback: Four Ways to Quickly Test Swift CodeTelerik Developer Network()

  • gari

    it doesn’t work at all. ;( even i used github.

    • Try giving it a shot again. I just updated this example to work with Swift 1.2 and the latest version of Xcode 6.

  • James Tilburn

    I’m still learning Swift and iOS development. I tried out this code and when I did some dumping of values I realized viewDidLoad only gets called once on initial execution of the app. So when I was entering data and then returning to the Task List tab there was no data. So I added the viewWillAppear method which executes every time the view is rendered and I added the tblTasks.reloadData() call and now my tasks appear in the list after I enter them.

    override func viewWillAppear(animated: Bool) {
    tblTasks.reloadData()
    }

    So is this the most efficient way of reloading the data? Anyone else run into issues? Thanks for the article, it would be great to see another series where the data persists between app launches.

    • That is what I used when I updated the sample to Swift 1.2.

  • Daniel Hjärtat Hjärtström

    hey!

    I am new to Swift and just tried out you tutorial. very nice and easy to follow, but when I run the app I get a breakpoint error at

    if (editingStyle == UITableViewCellEditingStyle.Delete)

    This comes up after i slide the cell from the left and press delete.

    How could I fix this?

    • Nik Edwards

      Click on debug at the top of toolbar, and deactivate breakpoints. that usually works, Daniel.

  • Dameon

    On mine it won’t transfer the task to the Task ViewController.

  • Dameon

    Never mInd I put in James Tilburns code and it got it to work. 🙂 Thx

  • marc

    Hello, i would like add a image with two text fiel. do you have an advice? thanks a lot