DPS923 MAP523 Lab 5

Two-level navigation-based app, with ‘add item’ and ‘edit item’ functionality, using Core Data for persistence.

.

DPS923 MAP523 Lab 5 – due Thu Feb 19

Due date: Thursday, February 19, 2015, at 9:45am ET

Grade value: 4% of your final course grade

.

Objective(s)

Navigation-based app style, with two levels (list and detail)

Use Core Data for persistence

Implement the ‘add item’ pattern

New… implement the ‘edit item’ pattern

.

Introduction to the problem that you will solve

You need an app that will manage a list of your school friends.

Sometimes you are in a group with one or two others. Sometimes you work with a friend in a course and help each other. Whatever the reason, you need a simple app to manage your list of school friends.

The app’s first view will be a table view, showing a list of names. Tapping one of the rows will display a ‘details’ page, with contact information about the friend.

A new friend can be added to the list.

Read through this assignment fully before starting work on it. That way you will know what’s coming.

These images are an example of what you will create:

friend-list friend-detail

.

friend-edit friend-edit-completed

.

Here’s a brief video that shows the app being used.

.

Specifications

Get started by copying the “ClassesV1” project template from the GitHub code repository. Follow the ‘rename project’ procedure, and the project’s new name will be “Friends”.

Next, you will perform these tasks:

  1. Design the Friend entity
  2. Generate custom subclass for the entity
  3. Create a fetched results controller for the friend collection
  4. Create a controller for the list view
  5. Create a controller for the detail view
  6. Create a controller for the ‘add item’ view
  7. Update and design the storyboard scenes/views
  8. Update the code in the app delegate and new controllers
  9. Clean up the project

.

Design the Friend entity

In the Core Data model editor, delete the existing “Example” entity.

Apple has a guide, last updated in September 2013, that may be somewhat useful:

Core Data Model Editor Help

.

Add a new entity, named “Friend”. Then add attributes:

object-model-friend

.

Generate custom subclass for the entity

Select the entity (in the model editor).

Then, on the Editor menu, choose “Create NSManagedObject Subclass…”.

It will create a “Friend.swift” source code file and Friend class.

Important:

One more task… follow these instructions to edit the name of the class in the Data Model Inspector.

Its class name must be fully qualified – in other words, it must be ‘projectName.className’.

.

At this point, you can probably build your app to ensure there are no compiler errors.

.

Create a fetched results controller for the friend collection

Study the Model class, and the existing NSFetchedResultsController property. Notice that it has three replaceable items:

  1. the property’s name
  2. the name of the entity
  3. the sort descriptors

We suggest that you copy-paste this code block to create a new property, and then edit/change the replaceable items.

The friends list shown above includes section headers. How do they appear? With a change to the fetched results controller creation, and (later) coding one more method in the controller.

Notice the parameter named sortDescriptors:. It accepts a comma-separated string of attributeName – sortOrder pairs. (The sortOrder is true for ascending sorts, and false for descending sorts.)

To use section headers, decide which attribute you want to use for the section headers. Then, use this as the first sort criterion, and then decide on a second criterion for sorting within a section.

For example, to use the course name as the section header, then sort by friend name within each section, the sortDescriptors: value will be:

course,true,friendName,true

Then, make sure you specify the attribute’s name in the andSectionNameKeyPath: argument. (Click the image below to open it full-size in its own tab/window.)

frc-with-sections

.

Create controllers

Create new controllers. Do NOT re-use the ‘example’ controllers that are in the template.

.

Create a controller for the list view

Add a new iOS > Source > Cocoa Touch Class.

Subclass of UITableViewController.

Name should be something like “FriendList”.

Other edits will be discussed later.

.

Create a controller for the detail view

Add a new iOS > Source > Cocoa Touch Class.

Subclass of UIViewController.

Name should be something like “FriendDetail”.

It needs a property to hold the Friend object that will be passed to it during the ‘list’ controller’s prepareForSegue(sender: ) method.

Other edits will be discussed later.

.

Create a controller for the ‘add item’ view

Add a new iOS > Source > Cocoa Touch Class.

Subclass of UIViewController.

Name should be something like “FriendEdit”.

Use the recently-learned ‘add-item’ pattern for this controller.

Other edits will be discussed later.

.

Update and design the storyboard scenes/views

The ClassesV1 template does include a storyboard with the navigation controller, and two scenes (list and details). The scenes point to ExampleList and ExampleDetail.

Change this. On each scene, click the controller icon (in the scene’s dock). Then, on the Identity Inspector, set the class to the appropriate new controller class (FriendList and FriendDetail).

Also, you should change the segue identifier (name). It should be ‘toFriendDetail’ or something like it.

Finally, add the ‘add item’ scene (and its navigation controller), as you learned recently.

friend-storyboard

.

Edit/design the ‘list’ scene

Change the title, to something like “Friends”. Any other changes? Probably not. (Other than those to support the ‘add item’ functionality.)

.

Edit/design the ‘details’ scene

Design the details scene to meet your need. You will probably use simple labels.

Add constraints, if necessary.

Make connections to outlets in the controller. Other edits will be discussed below.

.

Update the app delegate code

If you study the app delegate’s application(didFinishLaunchingWithOptions: ) method, you will notice that the table view controller was set to an “ExampleList” type.

Change that to a “FriendList” type.

.

Update the ‘list’ and ‘detail’ controller code

Study the code in the “FriendList” controller. It was created by the Xcode ‘new item’ template. The code is OK, but is not suitable for our purposes.

The code in the “ExampleList” controller is better. It is better-organized, and has all the features we need.

Therefore, a good strategy would be to:

  1. copy the code from ExampleList
  2. paste it to FriendList, replacing all the code
  3. edit to customize the code to the Friend entity

.

Therefore, do that. There are a number of places where you must edit the code, including:

  • the name of the class
  • in viewDidLoad(), the statement that assigns a fetched results controller to the frc variable
  • in configureCell(atIndexPath: ), which fetches a specific Friend object, and renders content from it
  • in prepareForSegue(sender: ), a number of edits are needed…
  • the segue identifier comparison string
  • fetching the specific Friend object
  • configuring the title of the destination view controller

.

As noted earlier, we want the friend list to display section headers. Add another method, which is a UITableViewDataSource protocol method. Its code extracts the current value of the section, and returns it as a string:

friend-list-section-header

.

Edits to FriendDetail

This is a simpler task.

Assign the values to the user interface labels. Use string interpolation when appropriate.

.

Formatting the date value

It is likely that your ‘date added’ value will not be formatted, as shown in the example to the right. To format it more readable, you must create and configure a date formatter object:

friend-detail-date-formatting

.

Implement the ‘add item’ pattern

This pattern was recently described on the February 10 notes page. Follow those instructions, and you will be able to successfully complete this task.

.

New – the ‘edit item’ pattern

Make sure the app works correctly before continuing.

In this section, you will learn how to implement the ‘edit item’ pattern.

.

Storyboard update (maybe)

Make a small change to the ‘add/edit’ scene on the storyboard. (This instruction has been added to the February 10 notes page, so you may already have done this.)

For the ‘add/edit’ scene, look at its Identity Inspector. Add a “Storyboard ID”; a suggested name is “AddEditFriend”.

.

Edit the FriendEdit controller code

Re-use the FriendEdit controller.

As part of the ‘add item’ pattern, it initialized with empty text fields. However, if we configure it with a Friend object, then it can initialize the text fields with the values from the friend object.

Note that we will not be able to edit the ‘dateAdded’ value. That’s OK. We could update it, if we wanted to.

.

Therefore, in the FriendEdit controller, make sure that you have a property for a Friend object:


var friend: Friend? // will be passed in by the presenting controller

.

Next, in the viewDidLoad() method, we need to check whether a Friend object was passed into the controller. If it was, then configure the user interface with its values.

if let f = friend {

    friendName.text = f.friendName
    course.text = f.course
    phone.text = f.phone
    email.text = f.email
}

.

The ‘save’ method must also be modified.

If a Friend object was passed in, then we simply update the object’s attributes with the values from the user interface.

Otherwise (if no object was passed in), then we can assume that it’s being used in ‘add item’ mode, so we’ll have to create a new Friend object, before configuring its attributes with the values from the user interface:

if friend == nil {

    friend = model.addNew("Friend") as? Friend
}

// Configure the object's attributes
friend?.friendName = friendName.text
friend?.course = course.text
friend?.phone = phone.text
friend?.email = email.text
friend?.dateAdded = NSDate()

delegate?.editItemDelegate(self, didEditItem: friend)

.

Edit the FriendDetail controller code

This controller needs a few changes:

  1. it needs to conform to the EditItemDelegate protocol
  2. it needs a programmatically-added button to enable the user to edit the current item
  3. it needs a button-handling method that presents the ‘add/edit’ controller and scene
  4. it also needs a method to handle the delegate callback from the ‘add/edit’ controller
  5. some code from viewDidLoad() needs to move to a new method, viewWillAppear()

.

Conform to the EditItemDelegate protocol 

class FriendDetail: UIViewController, EditItemDelegate {

.

Programmatically add a button to enable the user to edit the current item

In viewDidLoad(), add this code:

// Add an 'edit' button to the nav bar, right side

let editButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Edit, target: self, action: "edit")
self.navigationItem.rightBarButtonItem = editButton

.

Code a button-handling method that presents the ‘add/edit’ controller and scene

The code above creates a button that will call (‘action’) the “edit” method. Therefore, add that method:

func edit() {

    // Create a controller
    let vc = self.storyboard?.instantiateViewControllerWithIdentifier("AddEditFriend") as FriendEdit

    // Configure its properties
    vc.title = "Edit"
    vc.model = self.model
    vc.friend = self.detailItem
    vc.delegate = self

    // Present the controller, using the built-in 'push' navigation
    self.navigationController?.pushViewController(vc, animated: true)
}

.

Code a method to handle the delegate callback from the ‘add/edit’ controller

The code will be similar – although not exactly the same – as in the ‘list’ controller. However, here, the scene is presented in a ‘push’ manner, so the ‘dismiss’ call is a bit different.

self.model.saveChanges()

// Was pushed on to the navigation stack, so pop it
self.navigationController?.popViewControllerAnimated(true)

.

Move some code from viewDidLoad() to a new method, viewWillAppear()

The controller needs to update its scene when it first appears, and when it re-appears after an editing task. Therefore, move the user interface configuration code to a new method, named viewWillAppear(animated: ):

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    // This code was copied from the viewDidLoad() method
    // It handles initial load, as well as reload (after the 'edit' scene)

    friendName.text = detailItem.friendName
    course.text = detailItem.course
    phone.text = String(format: "Phone: \(detailItem.phone)")
    email.text = detailItem.email

    let date = NSDateFormatter.localizedStringFromDate(detailItem.dateAdded, dateStyle: NSDateFormatterStyle.LongStyle, timeStyle: NSDateFormatterStyle.NoStyle)

    dateAdded.text = String(format: "Added: \(date)")
}

.

Clean up the project

After the app runs correctly, you can clean up the project.

Remove the ExampleList and ExampleDetail controllers.

Make sure your source code is commented, where appropriate.

Are you interested in reformatting your source code? The easiest way is to select all (Command+A) in a source code file, and press Ctrl+I (which is Editor > Structure > Re-indent).

.

Submitting your work

Follow these instructions to submit your work:

  1. Make sure your project works correctly
  2. Locate your Friends project folder in Finder
  3. Right-click the folder, and choose Compress “Friends”, which creates a zip file (make sure the zip file is fairly small)
  4. Login to My.Seneca, and in this course’s Assignments area, look for the upload link, and submit your work there

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: