iOS Project Management App Tutorial – Part 2

Hello world! This is the last half of the Taskr post where we’ve been creating a project management app. In the previous post, we built the UI and the model of Taskr. In this post, we’re going to connect the model to our UI using the controller. The convenience methods that we built into the model will really shine here! We’ll also see how to handle notifications after they’ve been pushed.

Learn iOS by building real apps

Check out The Complete iOS Development Course – Build 14 Apps with Swift 2 on Zenva Academy to learn Swift 2 and iOS development from the ground-up with an expert trainer.

Before notifications, we should start connecting our model to our view. Open up the TaskrDetailViewController and let’s implement the save functionality. We can do this by using the initializer for the Task object. Then we can add that Task to the Singleton and return to the main list.

In the last line, we’re asking the navigation controller to go back to the root view controller (in other words, the controller that’s directly connected to the UINavigationController in the storyboard).

There’s a problem that we’ve been ignoring until now: the 64 notification limit. To preserve system resources and the user’s patience, iOS has as 64 notification limit. This means that the system will only schedule the first 64 notifications for your app. Afterwards, any requests to schedule are simply ignored.

There are several ways we can get around this limit. The simplest way is to not allow the user to schedule any more notifications. This is the simple approach that we’ll be taking. However, if that’s not an option for your app, you can schedule 64 notifications, and, At regular intervals, like when the app opens, you can check how many notifications are scheduled. If that number is less than 64, schedule the next set of notifications until you have scheduled 64. Using a queue data structure makes this approach even easier. You can dequeue the first 64 notifications, then, after some have fired off, dequeue more until you have scheduled 64.

We’ll just be disabling adding tasks when we’ve hit 64 scheduled notifications. In our TaskrTableViewController, add the following property and method.

This will disable the add action if we already have 64 notifications. We also need to tell the UITableView to redraw the cells. Speaking of UITableView, we can implement the override methods for the UITableView. We need to update the views when the UITableView is about to show. Since we have an array of tasks, implementing the tableView:numberOfSectionsInTableView and tableView:numberOfRowsInSection methods becomes trivial.

For tableView:cellForRowAtIndexPath, we need to dequeue a cell and get the task that corresponds to the UITableView row. We can then set the main text. For the detail text, we can convert an Date into a string using a formatter. You can look up the documentation on DateFormatter for exactly which sequence of characters produces which string. Then we can pass in the Date to be converted into a string. If this task is past the deadline, we change the color of all of the text of the row to be red, which is a nice visual clue to the user.

Let’s handle deletions. We can accomplish this using editing modes. First, we need to tell the UITableView that we support editing. Then, if we’re deleting, we remove the task from the array, the Singleton array, and the UITableView. We also need to enable the add button since we’re definitely under 64 items by our app design.

Now we can move on to notifications. There are a few issues we should fix. We need to refresh the UITableView when a notification is fired off in case the user took action on it and when the app is resumed as well. Luckily, iOS supports the Observer pattern through the NSNotificationCenter class (not to be confused with UILocalNotification!)

In the Observer pattern, we have any number of observers that are registered to execute code whenever an event is fired. We can register an observer to refresh the UITableView whenever a notification was fired and when the app is resumed. Open up the TaskrTableViewController and add the following method.

This will register the observer to refresh the list when the TaskListRefresh event is fired. Open up the AppDelegate class and add the following code to the respective methods.

This will fire the event when a notification is fired or when the app resumes. Now let’s move on to badging the app icon. There are two times when we need to update the badge: immediately after the user quits the app and when a new task is added or removed. We can handle the first case in our AppDelegate class like the following.

To add a bit of variety, we’re using a trailing closure while implementing the closure for the filter method. This filter method does exactly what the name implies: filters elements of an array using criteria. For the second scenario, we can create a method to update badge numbers whenever a task is created or deleted in our TaskList class.

Since there’s no way to update an already-scheduled notification, we need to cancel it and reschedule it. Make sure that you call this method at the end of addTask

and removeTask.

Since iOS 8, we can add actions to notifications. Let’s add an action to complete the task in the notification. We have to configure these options back in the AppDelegate. We create a new UIMutableUserNotificationAction for each action and set their various properties. The activationMode can run the command in the background (.Background) or bring up the app (.Foreground). The authenticationRequired property requires the user to unlock their phone before executing this operation. The destructive property simply colors the background of the action red to indicate to the user that this operation is destructive.

Then we need to create a category and put this action in the category as the default ordering of the actions. Finally, we need to change our call to registerUserNotificationSettings to add that category instead of nil. Double-check that the identifier of the category matches the category in the addTask method of the TaskList class.

Notice that this only configures the notification actions; this does not tell the system what to do when those action are called! For that we need to implement another method in the AppDelegate: application:handleActionWithIdentifier:forLocalNotification.

In this piece of code, we build a pseudo-task from the information in the notification. For the removeTask method to work, we really only need the correct ID stored in the userInfo dictionary in the notification. The title, description, and deadline can really be anything as long as the ID is correct. Then we use a switch case for the identifier to make sure we have the right identifier. This is also for future-proofing our app in case we want to add more actions later. Finally, we execute the completionHandler closure since we’re supposed to by documentation.

That’s all we need for our Taskr app! Let’s run it and see it work! Below are some screenshots.

Taskr - 8

Taskr - 9

Taskr - 11

Taskr - 12

Taskr - 13

In two posts, we have successfully built a project management app Taskr that can keep track of different tasks we need to accomplish. It also keeps track of deadlines and can notify the user at these deadlines. We have learned much about iOS over these two posts about data persistence, notifications, badging the app icon. We also learned about some Swift constructs such as the filter, map, and sort methods, computed properties, and trailing closures.

Published by

Mohit Deshpande

Mohit Deshpande is a professional mobile application developer, contractor, and instructor. He started programming at the age of eleven. During the great mobile revolution, he shifted focus to developing mobile apps with his first Android app running on a Samsung Galaxy S1 running Android 2.1 Eclair. Since then, he has been involved in industry and research. He is a computer science and engineering student at The Ohio State University and works for the Department of Computer Science and Engineering as a researcher. During the university hackathon, he came in second place with an Android app that links a task with a location using a geofence. In what little spare time he has, he plays jazz and rock guitar and performs in the Ohio State Athletic Band on trumpet at various sporting events.

Share this article

2
Leave a Reply

avatar
1 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
Mohit DeshpandeTim Vogt Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Tim Vogt
Guest
Tim Vogt

let taskArray = items.map({Task(ID: $0[“ID”] as!

error: /Downloads/Taskr/Taskr/TaskList.swift:38:47: Type ‘Any’ has no subscript members