SICT

DPS923 & MAP523

Mobile App Development for iOS

Notes Topics Weekly Resources Graded work Professor Code examples

DPS923 and MAP523 Assignment 4

Assignment 4 enables you to work with Core Data technologies, location services, and mapping.

Read/skim all of this document before you begin work.

While you are doing the work, if a specific task is not clear, or it seems to require an unreasonable amount of time to complete, contact your professor.


Due Date

Monday, April 13, 2020, at 11:00pm ET
Grade value: 18% of your final course grade

If you wish to submit the assignment before the due date and time, you can do that.

It is VERY IMPORTANT to submit your work before the due date and time.
This assignment CANNOT be late.
If it is not submitted by the due date and time, your Assignment 4 grade will be zero.


Overview and purpose

We need an app that will enable you to capture and store information about the food you eat during the day.

It is important for everyone to have good nutrition habits. Diet and nutrition issues are too easy for people to ignore and dismiss as unimportant, but good food brings health, both in body and in mind. Modern society and culture have increased interest in food and health, so an app like this could be useful.

In general, the app features include:

Here are some sample screen capture images… your scenes may look different.

The “first launch” scene, which is a list of meals, and an info scene about a tapped/selected meal:

Meal listMeal info

Add meal scenes, with keyboard visible during editing, and then after “Done editing notes”:

Add meal in progressAdd meal done info

Tap the “Food item list” button to view the meal’s food item list, and after that, tap the “+” (add) button:

Food item list

Search for a food item, setup, and list of possibles:

Food item addFood search list

After selecting an item on the list, before and after saving:

Food item selectedFood list after

If you view the list of food items in a meal, and then drill down to a food item, this is what you’ll see:

Food item listFood item info


DPS923 students will have a few additional specifications.


Getting started

Use the most recent version of the TemplateCD..., and create a project, probably named FoodDiary.

Create a Core Data model. There will be three (3) entities:

Each entity must have the attributes it needs to implement the specifications. You may have to revise your data model as you work on the assignment. As an example, it could end up looking something like the following:

Core Data model

The “photo” attribute will be a “Binary Data” type, configured for “Allows External Storage”. To and from Swift, a photo is a Data type, so you’ll have to marshal it back-and-forth to an image when you display it (or capture it with a camera).

This was a Week 11 document that discussed this topic:
Core Data and photos


Build the navigation workflow

The idea in this section is to build the four-scene data-viewing workflow, using programmatically-generated data, before we get the “add” tasks and the web API involved. It will enable faster progress, easier testing, and improved confidence.

Edit the project to display Meal objects:

At this point, your meal list may look something like this:

List

Next, add a meal scene:

At this point, your meal scene may look something like this:

Scene

Next, add a food consumed list:

Tip:
The data source for this food list must be a fetched results controller (frc).
Later, we’ll be adding items to the list, and the frc will easily enable the list update task.
Here’s a reminder about the way to think about building this frc.

At this point, your food consumed list may look something like this:

List

Finally, add a food consumed scene:

At this point, your food consumed scene may look something like this:

Scene


Checkpoint

At this point, you should have the four-scene data-viewing workflow, using statically-generated data.


Meal add workflow

Above, you used the built-in template method to add a new meal (and a few food consumed items) programmatically. In this section, we will code the actual “add item” workflows.

Adding a meal will be done incrementally:


Add pattern, to add a new meal object

Break the connection between the meal list scene’s “add” button and the method that handles the programmatic add task.

Add a controller for the “add new” meal task. You can create it from scratch, or you can use some code from an appropriate file in the Templates folder.

In the save(_:) method, if you wish, you can add a few food consumed items programmatically. That will enable testing, and you can remove the code later/soon.

Do the rest of the work to add, configure, and code a scene and segue (from the meal list controller).

At this point, your add meal scene may look something like this:

Add setup

And the result will be added to the list (which you can drill down into and see food consumed items, if you programmatically added them as suggested above).

Add result


Checkpoint

Make sure that you can add a meal, before continuing.


What’s next?

What’s next? During the “add meal” task, we want the user to interactively add “food consumed” items. We will use a web API to help with this task.


Web API introduction

The United States Department of Agriculture has a web API named “FoodData Central”. Visit the web site, and learn something about the service.

This is a BIG data source. It has thousands of food and nutrient items.

To use the web API, you must have an “API Key”. This is a string. It must be sent with every request to the web API. Follow the “Get an API Key” link in the middle of the page. You can use a College or personal email address. It will display your API key, and also send it to your email address.


Interact with the web API

Now, interact with the web API. How? Use Postman.

As you will read (follow the “API GUIDE” link), it offers two endpoints:

The following is an example of the “Food Search”. In Postman, configure:

{
    "generalSearchInput": "peas fresh",
    "requireAllWords": true,
    "brandOwner": "monte",
    "includeDataTypes": {
        "Branded": true
    }
}

On March 9, 2020, at 8:05am, this request returned one result. Notice a few things:

Notice the results include a fdcId key, and its value is a six-digit integer. That’s the unique food identifier we need for the next query.

The following is an example of the “Food Details”. In Postman, configure:

Notice the URL - the six-digit integer replaces the static word “search” that you saw before.

On March 9, 2020, at 8:10am, this request returned a detailed result. Notice a few things:

Experiment on your own. The documentation is useful.


Design and define structs for the web API interactions

Design and define structs for the web API POST request, and for both kinds of results.

Food Search, send (request)

Use the JSON above to guide your design for the struct used in the Food Search entity body.

If needed, use the Web API and data structures document to help with this task and the ones that follow.

Food Search, receive (response)

For the Food Search result, you are really interested in the foods array of items. Each food will definitely have a fdcId property. It will likely have a description property, but in general, maybe you should define most of the properties (other than fdcId) as optional. It is NOT necessary to code them all.

Food Details, receive (response)

For the Food Details result, it has a number of properties that may be useful to us and of interest to you:

It has two embedded data structures:


Test the API in your app, checkpoint

If you wish, adapt one of your controllers temporarily, by adding code that will do each kind of requests (food search, and food details). It’s important to know that the structs are correct, and that encoding (for the POST request) and decoding (for the GET request) are working correctly.

This will not be throw-away work, because you can keep and re-use the code in the controllers that actually interact with the web API.


Add pattern, food consumed item

Now, we will replace the programmatically-generated food consumed items, for a meal, with the ability for the user to search for a food item. Therefore, we will modify the “add meal” scene. It will navigate to a list of food items (in that meal). That list will enable new items to be added to it, and those new items can be helped by a “select list” of results from a web API call.

Wait - we already have done a food list. Do we have to make another? Well, we have a choice - we can make another (and it will be almost the same as the other food list), or we can re-use the food list, and modify it to enable the “add” functionality.

To prepare for either choice, create a new standard view controller for the food item “add new” pattern. Most of its code can be copied from the add meal controller and then edited, or you can write it from scratch.

It needs a Meal property. When the controller loads, create a new meal object. Why? We must set the relation between an existing meal and the food items that we will add soon. However, please note that you must delete the meal object if the user taps the cancel button - you don’t want to save partially-configured objects that are not desired.

You can do this task in two phases.
Phase 1, hand-type the food consumed item details.
Phase 2, get the data from the web API.

Here are some preview images to guide you:

The following is the food item list scene. Notice the “add” button (+). It will modally present a scene with data entry fields.

Search 1

The following is a food item add scene. Enter the food description and brand owner. The idea is that a user can hand-enter the info, or use the search feature. The food item name is required, but the brand owner is optional. If you do not know any brand owner values, leave that field empty, and then look at the results for ideas. Then cancel out of the search, and run it again, and include a brand owner value. Remember, when you segue to the search scene, you must pass in these two values (food item name, brand owner).

Search 2

After “Search” button tapped, a list scene appears. It implements the new-to-you “select list” pattern that you learned in class during Week 11 of the course. (Yes, it’s supported by a code example etc.) For best results, add the web API request code to the controller’s load method.

Search 3

Selecting an item from the list fills in the “Add Food Item” fields:

Search 4

Tapping “Save” adds the item to the food item list for the meal.

Search 5

Here’s a brief video, for Safari users only:

View this in the Safari browser


Checkpoint

At this point, the essential features of the “add meal” (and “add food items”) tasks will be done. Make sure it works successfully, before moving on to the improvements and refinements.


Improvements to the user interface

To reach this point, you have the two major “flows” of the app completed (display meal and food items, and add meal and food items). However, during that work, we didn’t pay much attention to the user interface and full functionality. In this section, we will improve and refine the app.

Here’s a list of tasks that must be done:


DPS923 additional functionality

DPS923 students must implement the following additional functionality:

  1. Use/display sections in the meal list (by date)
  2. Allow the user to select the meal’s date in the add scene (use a date picker)
  3. Sum the macronutrients of all the food items in the meal
  4. Use a segue “guard”, before attempting to search the web API


Display sections in the meal list (by date)

Modify the meal list controller so that it displays section headers (titles).

Meal list with sections

The Meal entity includes a date attribute, which is a value that has time info in it (hours, minutes, seconds). We cannot use the date attribute for the section header, because it will create a separate section header for each Meal object.

Therefore, we want just the year, month, date parts. Therefore, think about and code a date formatter that will generate a date in the format that you like.

To implement this, we will create a Swift extension, which will add a new read-only computed property to the Meal entity class. Wow.

Add the following to the bottom of the data model classes source code file, or add a new source code file named Meal+SectionInfo.swift.

extension Meal {
    @objc var sectionDate: String {
        get {
            // Create a date formatter object (e.g. "df")
            // Set its format to something you like
            return df.string(from: self.date!)
        }
    }
}

Next, modify the code that creates the fetched results controller. It must sort by the date attribute. And the section name key path must be this new property, sectionDate.


Select the meal’s date in the add scene (use a date picker)

Add a date picker to the meal add scene. Its initial value will be the current date-and-time.


Sum the macronutrients of all the food items in the meal

This is an example of the meal info scene, showing the sum of all food item macronutrients:

Meal scene


Use a segue “guard”

The NWPathMonitor class enables us to check for network connectivity. Read something about it here (and look elsewhere if you want to).

To simplify this task, monitor only the “wifi” network. (You do not have to fully consider all network types.)

This code can be placed inside a segue “guard” method that you will add to the controller that presents the list of web API search results. A sample implementation could look like this:

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {

    if identifier == "toFoodSearch" {

        // Validate data...

        // Validate network connectivity

        // If all is good, return true
        // Otherwise, return false
    }
    return true
}


Testing your work

Test your work by running it on the simulator. Do this frequently and incrementally, after making any substantial changes. And, use the Xcode debugger to help.

When the app is complete, create screen captures, of each scene. Use a naming convention for the image names, something like this:
MealList
MealScene
FoodItemList
FoodItemScene
MealAdd
FoodItemAdd
FoodItemSearch
etc.

Also, a request: Each screen capture could possibly be large. If you open the png file in the Preview app, there is a feature on the Tools menu named Adjust Size. Change its width to 400 pixels (and it will automatically adjust the height). Then save, and it will reduce the size, sometimes dramatically.


Reminder about academic honesty

When you are ready to submit your work, you will copy some of the code in your project to plain text files, so that the My.Seneca/Blackboard “SafeAssign” tool can do its job. The next section will tell you which files to copy.

From the Blackboard web site:
SafeAssign compares submitted assignments against a set of academic papers to identify areas of overlap between the submitted assignment and existing works.


Submitting your work

Follow these instructions to submit your work, before the due date and time:

  1. Locate your project folder in Finder (and we suggest that you make a copy for yourself).

  2. At the same level, create a new folder named “MyCode”.

  3. From the project folder(s), copy these source code files to the “MyCode” folder:
    ( all your controllers )
    DataModelClasses.swift
    DataModelManager.swift
    Main.storyboard
    For each of these files, change the file name extension to “txt”.

  4. From wherever, copy the screen captures into the MyCode folder.

  5. Select the top-level folders:
    (project)
    MyCode
    Right-click, and choose Compress 2 Items, which creates a zip file. The zip file may be sizeable, with all of the screen captures.

  6. Login to Blackboard/My.Seneca, and in this course’s Assignments area, look for the upload link, and submit your work there.