DPS923 notes – Thu Mar 27

Topics useful for the programming assignment.

.

Topics:

  • Today’s class
  • Web service
  • Tactic for handling add and edit with one controller
  • Segue from the ‘equipment categories’ controller to equipment-specific scenes
  • Using Team and Player objects from the web service

.

Today’s class

Today’s class will focus on topics for the programming assignment.

Your professor will not be presenting any/many new topics. If you need help or advice, you will get it there.

The Mac-equipped lab rooms have classes at the same time as our class. So, depending on demand, we can move to the library (learning commons) if we need to.

.

Web service

A web service has been created and publicly posted. Its base URL is:

http://equipservices.azurewebsites.net

Sample resource paths include teams, players, and so on. Use the JSON Formatter & Validator to inspect the results. The digit “1” is the host (web service) unique object identifier.

http://equipservices.azurewebsites.net/api/teams

http://equipservices.azurewebsites.net/api/teams/1

http://equipservices.azurewebsites.net/api/teams/1?players

http://equipservices.azurewebsites.net/api/players

http://equipservices.azurewebsites.net/api/players/1

http://equipservices.azurewebsites.net/api/manufacturer

http://equipservices.azurewebsites.net/api/manufacturer/1

http://equipservices.azurewebsites.net/api/brands

http://equipservices.azurewebsites.net/api/brands/1

http://equipservices.azurewebsites.net/api/helmets

http://equipservices.azurewebsites.net/api/helmets/1

(etc. for sticks and so on)

.

Starter data

In the next few days, starter data will be loaded for Team and Player entities.

There will be 24 teams (from the AHL, the American Hockey League). Your professor plans to assign each student a team.

There will be 600+ players loaded too. No photos however. The AHL web site was not conducive to an easy way to screen-scrape player photos. (Your professor is confident that there’s a scripted way to do this, but he doesn’t have time to do that right now.)

As previously noted, you will load the data when the app launches for the first time on a device.

More details soon.

.

Tactic for handling add and edit with one controller

OK… we have talked about a scenario where one single controller would work for both add and edit situations. Players, equipment items, whatever.

The idea is that the controller’s viewDidLoad: method would check whether there was an object assigned to its “o” declared property. (A typical add/edit controller has both a “model” and an “o” declared property.)

The incoming object could be a custom NSManagedObject subclass (common) or an NSDictionary (less common).

In the ‘save’ method, you call back to the delegate, and pass the object:

If the controller’s being used to add a new object, an NSDictionary object is passed back

However, if the controller’s being used to edit an existing custom NSManagedObject subclass object, then we need to think about this differently.

(save the object in the add/edit controller, then pass back nil)

(or, pass back the object, and handle the situation there)

(hmmm…)

.

Segue from the ‘equipment categories’ scene

In class, we discussed what happens when you use the list of players.

(These screenshots are from an app created by one of the students in the class.)

players-list

.

We know what happens when you tap the “detail disclosure” accessory (the circled “i” button). It navigates to a ‘detail’ view for the selected row. In other words, you see something like this:

player-detail

.

However, we’re more interested in the equipment categories right now. Tapping one of the player rows will show something like this:

equipment-categories

.

Your app should already have this functionality. The following is new.

Please note that you should design this functionality by thinking about it and sketching it out, before you begin coding. That will help you understand what you want to do.

After additional thought and coding, your professor recommends that you create a separate scene and controller for each equipment category. Why?

  1. Coding effort will be lower
  2. In this app, you will need to code a special scene and controller for skates
  3. In the future (which you don’t really care about), changes are more easily handled

In the following instructions, we’ll focus on the ‘helmet’ equipment category. The approach for the others will be similar (except for skates, explained later).

So, what do you need?

.

Storyboard – detail “View Controller” scene to show the equipment details

On the storyboard, add a standard “View Controller” scene.

Click/select the ‘equipment categories’ scene. Create a segue, from the yellow view controller icon on this scene’s dock, to the new scene you just added. Set the segue identifier (to something like “toHelmetView”).

.

Controller for the equipment details

Create a new UIViewController subclass, maybe named “HelmetView”.

On the storyboard, match it to the scene you added in the previous step.

Then, add and configure whatever user interface objects you need on the scene, and outlets for them in the controller.

The controller will also need properties for 1) the Model object, 2) the Player object, and 3) the equipment item (i.e. Helmet object).

.

Now what?

You have a new scene and controller. Let’s make it show up. What do you need?

1. A method in the Model class that will fetch the data that you need.

2. Methods in the ‘equipment categories’ table view controller to handle the row tap / selection action.

.

Model class method

Add a new method to the Model class. Continuing the ‘helmet’ example from above, you can name to capture the ‘get helmet for player’ intention. The method will accept a Player object as a parameter. It will return a Helmet object.

A standard ‘fetch request ‘ – an instance of NSFetchRequest – will fetch the specific helmet object for a specific player.

Now, you have a choice to make:

1. You can fetch the Player object that matches the incoming Player argument. (Then you will return that Player object’s “helmet” property.)

2., Or, you can fetch the Helmet object by looking in its “players” property (collection) to match the incoming Player argument.

Either approach is fine.

If you choose #1, here’s the pseudocode:

fetch-helmet-by-matching-player

.

Alternatively, if you choose #2, here’s the pseudocode:

fetch-helmet-by-matching-helmet

.

Equipment categories controller code, handling the row tap / select

A user taps / selects a row. Handle that with the tableView:didSelectRowAtIndexPath: method.

Here’s the pseudocode:

equip-cats-did-select-row

.

Equipment categories controller code, performing the segue

Code in this method is similar to what you’ve done before. The key task is to fetch the equipment item, using the new Model class method you added earlier.

Here’s the pseudocode:

equip-cats-perform-segue

.

Displaying equipment item details

In the “HelmetView” controller, write code to set the outlet properties to the values in the incoming Helmet object.

player-helmet-info

.

Changing an equipment item for a specific player

In the screen shot above, you see the “Change” button on the nav bar (right side).

When a user taps that button, it will do the following. We will continue to use the ‘helmet’ equipment category.

Show a table view controller, which will hold a list of helmets. This table view controller is embedded in a ‘navigation controller’, and presented using a modal segue.

Use the Editor > Embed menu to help embed a controller in a navigation controller.

This table view controller will be used as a ‘select list’, and not for navigation. Therefore, the presenting controller – “HelmetView” – will need to adopt a protocol, and implement a delegate method, etc.

See the February 10 class notes page, and the “TVS Single” code example, for more.

Each row in this table view will NOT have a standard disclosure accessory.

However, it is possible that we’ll add a ‘detail disclosure’ accessory soon, to support info/detail drill-down.

We suggest that you add a ‘cancel’ button to the left side of the nav bar, which allows the user to cancel the task.

And for another task (described later), add an ‘add’ ( + ) button to the right side of the nav bar.

helmet-list-from-web-service

The data will come from the web service.

Therefore, you need Model class support for a collection of helmets from the web service. The data comes in asynchronously, so make sure that you update the table view when the data appears. Treat it like any other list-of-items-from-a-web-service task.

When the user taps / selects a row…

1. Fetch the object – which is an NSDictionary – from the array.

2. Pass back that object to the presenting controller, “HelmetView”.

3. In the delegate method, save the data from the selected helmet NSDictionary object as a “Helmet” object in the device store. At the end of the method, the presenting HelmetView scene will be visible.

4. Update the HelmetView visible properties with the new data.

.

These instructions should help you make progress.

.

Adding a NEW equipment item

From the previous section, when you’re viewing the list of helmets from the web service, your app will enable the user to add a new helmet.

Present the ‘add/edit helmet’ controller modally (again, embedded in a navigation controller, so you can add ‘cancel’ and ‘save’ buttons).

After gathering and validating the data…

1. Package it as an NSDictionary.

2. Pass back that object to the presenting controller, “HelmetList”.

3. In the delegate method, use a new Model class method to send it as a POST request to the web service. At the end of the method, the presenting HelmetList scene will be visible.

4. Update the HelmetList scene with the list that has the new helmet object.

.

At that point, the user can select that new item if they wish, or do something else.

.

Using Team and Player objects from the web service

In class, we discussed that every student will work with their own Team and Player objects.

A personalized email will be sent to each student with this information. It includes the web service URLs used to get the data.

If you can use this new information for the assignment part 2 (due tomorrow), then go ahead and use it. Otherwise, use it as soon as you can.

.

Your app startup logic must change

Your current app creates a Team object and some Player objects in the store initializer class. Now, you will not create those objects in the store initializer. Go ahead and comment out those statements.

Instead, you will initialize the app’s data in your Login class.

.

Custom (individual) team 

Every student received a custom individual email message, with information about their team. Use the data about your own team and players.

Visit the team URL by using the JSON Formatter & Validator.

You will notice EMName and EMUsername properties. For example, …/team/26 is your professor’s team, the Utica Comets. John Forget is the equipment manager (EM), and his user name is john.forget.

Next, visit the professor’s Authentication and Token service, and create an account for the equipment manager.

YOU MUST use the exact user name that you see in YOUR team object. For example, the user name for your professor’s team is – as noted above – john.forget. You can use/create any password that you like and will remember.

Then, you MUST use these credentials for the rest of the semester. As you will read below, the user names must match.

.

New startup sequence (overview)

login-final-400pxThis is a brief overview of the new startup sequence. It is more fully described below.

It is diagrammed in the flowchart on the right. Click the image to see it full size in a new tab/window.

The “startup” work will be done in the Login and Model classes.

In the Model class, we need properties and methods to support the storage and fetching of Team and Player objects.

In the Login class, gather the credentials, like before.

If there is a Team object, compare the user name input with the “username” property of the Team object.

  • If they match, can continue.
  • If they do not match, display an error.

If there is no Team object, it means that the app is being launched for the first time on the device. Continue.

Login using the web service. Wait for the answer. Similar to the old way.

If a authorization token is received, the login was successful. Continue.

Otherwise, display an error.

If there is a Team object, clean up after the login process, and segue to the player list.

If there is no Team object, it means (as above) that the app is being launched for the first time on the device.

Therefore, call the method (in the Model class) that fetches the Team object from the web service.

Then, clean up after the login process, and segue to the player list.

The Model class method that fetches the Team object will complete its work, and then call another Model class method that fetches the Player objects for that team.

.

Login and startup sequence (details)

The Login class in your professor’s version of the app has these general features:

  • an “authToken” declared property (NSString)
  • an IBAction method named “loginRequest” to handle the “Login” button tap
  • in viewDidLoad, it adds an observer for the login request notification
  • a method that handles the notification message, maybe called “loginResponse”
  • implements the viewWillAppear: method, which sets the value of “authToken” to an empty string (why?)

.

Login class, loginRequest method

The “loginRequest” method handles the work shown in the top part of the diagram:

  • Team object exists?
  • Matching user names?
  • Login using the web service

Locate the first yellow-coloured process rectangle (titled “Login using the web service”).

Create a WebServiceRequest object, and configure it with the URL of the authentication service, complete with the user name and password. Then, execute it. If you’ve designed your code correctly, the method that handles the notification message (that happens as a result of a successful login) runs.

.

Login class, loginResponse method

The “loginResponse” method handles the work shown in the bottom part of the diagram:

  • Successful login, receive token?
  • Team object exists?
  • call the Model class method named “fetchTeamRequest”

Locate the last blue-coloured decision diamond (titled “Team object exists?”).

If the answer is “no”, it means that the app was just installed on the device, and we need to fetch the team and player data from the web service.

That process is started by calling the Model class method “fetchTeamRequest”, which is described below.

After the statement that calls the “fetchTeamRequest” method, segue to the player list scene. The list will be empty, but that’s OK. Why?

The “fetchTeamRequest” method will send a request to the web service, and wait for the response. The request runs in the background, and after some time, the response – a Team object – will come back.

Assuming it’s successful, its response handler save the Team data, and will then call the “fetchPlayersRequest” method, which sends another request to the web service. That request also runs in the background, and after some time, the response – a collection of Player objects – will come back.

Its response handler will save the Player data. How does the Player data show up on the player list scene? Well, if you’ve done your job (fetched results controller for the Player data, a table view controller that implements the NSFetchedResultsControllerDelegate protocol, and implemented methods to reload the table view), then the Player data shows up auto-magically. Why? The first time the player list scene is rendered, there are no players. The fetched results controller’s fetchedObjects collection is empty, and you get an empty list. After the time-delayed background task completes, and the locally-stored Player objects get created, the fetched results controller will detect that it needs to be refreshed.

.

Model class declared properties and methods

You probably have the following declared properties in your Model class:

  • NSString object to hold the authorization token (“authToken”)
  • Team object (“team”), which has a custom getter, with a standalone fetch request for the single Team object
  • Fetched results controller object (“frc_player”) to hold the collection of Player objects

.

The Model class needs three (3) new members to support the first yellow box, “Fetch Team object…”:

  1. method “fetchTeamRequest”
  2. declared property “fetchedTeam”
  3. method “fetchTeamResponse”

.

Method “fetchTeamRequest”

Accepts one argument, which is the equipment manager’s user name. Void return type.

Creates, configures, and executes a WebServiceRequest object, to…
/api/teams?managerusername=john.forget

Make sure the response comes back to the declared property “fetchedTeam”.

Register the “fetchTeamResponse” method to handle the notification that’s generated by the WebServiceRequest object.

.

Declared property “fetchedTeam”

From the JSON response data, use the “Item” key-value pair. Will be an NSDictionary. Does not need a custom getter. Its data will be set by the result of the “fetchTeamRequest” method.

.

Method “fetchTeamResponse”

Similar design to other notification-handling methods that you’ve written. Void return type.

Its first task will use the “fetchedTeam” data to create and save a Team object in the local store.

Its second task will use the team identifier value, and call the “fetchPlayersRequest” method that’s described below.

.

The Model class needs three (3) new members to support the second yellow box, “Fetch Player objects…”:

  1. method “fetchPlayersRequest”
  2. declared property “fetchedPlayers”
  3. method “fetchPlayersResponse”

.

Method “fetchPlayersRequest”

Accepts one argument, which is the Team object’s unique (web service) identifier. Void return type.

Creates, configures, and executes a WebServiceRequest object, to…
/api/players?team=26

Make sure the response comes back to the declared property “fetchedPlayers”.

Register the “fetchPlayersResponse” method to handle the notification that’s generated by the WebServiceRequest object.

.

Declared property “fetchedPlayers”

From the JSON response data, use the “Collection” key-value pair. Will be an NSArray. Does not need a custom getter. Its data will be set by the result of the “fetchPlayersRequest” method.

.

Method “fetchPlayersResponse”

Similar design to other notification-handling methods that you’ve written. Void return type.

It will use the “fetchedPlayers” data to create and save Player objects in the local store.

.

Need help? Ask.

.

.

.

.

.

.

.

.

.

.

.

.

.

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: