Resources:


Due April 16
For this assignment, we will continue to use the Assignment 3 Git Repository
This assignment is available as a PDF.
For those of you who would like to get ahead, here are a few of the things we’ll be working on in the next few weeks. Completing these early will earn you some extra credit on the programming assignments, and will also give you more time to work on your final project.
These exercises are extended to be self-driven. We’ll go into more detail on some of these in future assignments.
From now on we’ll be working off of your Assignment 3 Git Repository for all enhancements to the restaurant app.
Create an array of restaurants in the MasterViewController
(See Table View Programming Guide)
Populate the table with the contents of the array
Display the name of each restaurant in the table
Pass the restaurant to the DetailViewController through the segue
Add the filename of the image to the Restaurant class
There are 2 ways to do this: either assign a number to each image and save all the images as numbers (3.png) or just use a custom name and store it as a property.
Modify DetailViewController to show the image for each restaurant
Modify DetailViewController to show the map of the restaurant (Read: MKMapView Class Reference)
Add a button to DetailViewController to show the map larger on a new view Tip: Cover the mini-map with a button, so users are shown more when they tap on it. Perform a Segue to a new view.
Add a way to change from the list view (MasterViewController) to a map view with all of the restaurants as points. Add annotations to the map, make them segue to the DetailViewController
The goal of this assignment is to modify the restaurant to add reviews. For now, we’ll display the review as follows:


You’ll need to do the following:
In order to do these things, you’ll need to understand these topics. We’ve already covered those in italics.
Let’s get started!
Fork and Clone Mobile Media Assignment 3 using GitHub for Mac.
Open the project and ensure it runs.
If you look inside viewDidLoad in DetailViewController.m, you will see that we are defining a Restaurant to display on that screen, and then a number of reviews (commented out).
However, we haven’t defined a Review class yet.
Define a Review class, with the following properties
NSString* reviewerName;
NSString* text;
int score; //(1 to 5, how good the reviewer thought the restaurant was)
int numberOfHelpfulRatings;
int numberOfUnhelpfulRatings;
Tips:
Uncomment the lines in the view controller (select them and hit command-/).
Run the application.
If you wrote your Review class correctly, your application should run without errors.
Before we get into handling all the reviews, let’s display a single review on the screen. You will see that the IBOutlets for each of the new elements in the storyboard has already been created for you in the DetailViewController class.
Change helpfulReviewLabel’s text property to display the text of review1 followed by the reviewerName.
Change helpfulReviewPercentageLabel to display the number of helpful ratings and the total number of ratings.
It should end up looking like this:
What fab-u-lass chicken! We could eat it all day if we didn’t have to stop to drink sangria! — The Addams”
*Most helpful review — 19 of 27 found this review helpful
As we’ve built it up thus far, review1, review2, review3, and review4, only exist for a moment: we create them in the detail controller’s viewDidLoad method, we take the values for the review1 for display, then when the viewDidLoad method ends, all of these variables leave the computer’s memory.
We need to store these in Restaurant. But, it wouldn’t make sense just to add a new property called “review1” on Restaurant: we need to be able to hold any number of user reviews.
That’s where arrays come in. In Objective-C, there are 3 common ways to store collections of objects:
Because it will be easy to go through the reviews 1 by 1 if they are in an NSArray, we’ll use that. You will find that the majority of collections in Objective-C are NSArrays.
The basics of using an NSArray:
NSArray* array = [[NSArray alloc] initWithObjects:@"First",@"Second",@"Third", nil]; //nil indicates the end of the list
NSString* firstObject = [array objectAtIndex:0];
NSString* thirdObject = [array objectAtIndex:2];
It may seem a little strange to count from zero, but that is the standard for most programming languages.
Define an NSArray* reviews property on your restaurant class.
In the View Controller’s viewDidLoad method, set this property to a new NSArray containing the 4 reviews.
Tips:
restaurant.reviews = [[NSArray alloc] initWithObjects:review1, review2, review3,review4, nil];nil represents nothing. In other languages it is often called NULL, and in fact, you can use NULL in Objective-C and it will work. However, nil is the standard we go by.
It’s very helpful to be able to represent nothing. In fact, as long as your property represented an object (look for the *) it’s value will be nil until you set it.
Nil is also useful when writing methods that return something: what if there is no way to get the thing you are asking for? For instance:
NSArray* array1 = [[NSArray alloc] initWithObjects:@"First",@"Second",@"Third", nil];
NSArray* array2 = [[NSArray alloc] initWithObjects:@"Fourth",@"Fifth",@"Sixth", nil];
NSString* firstObjectInCommon = [array firstObjectCommonWithArray:array2];
In this case, we were hunting for the first object in common. Since there were no objects in common, the firstObjectCommonWithArray: method returned nil.
Note: It’s legal to send messages to nil. It just doesn’t do anything, and returns nil. Example: [nil doSomething] will not crash your app.
We now want to change the review we are showing from review1 to the most helpful review in the reviews collection. We do this by looping.
There are 3 commonly used loops in Objective-C: for, for with fast enumeration, and while. We’ll discuss the first 2 now, since those will be all you’ll need for this course.
The basic for loop:
for (int i = 0; i < 5; i++) {
NSLog(@"Pass number %i", i);
}
This starts at 0 and counts up to 4. In one line, it does the following things:
i, and sets it’s value to 0i to 5. The output from this like this:
Pass number 0
Pass number 1
Pass number 2
Pass number 3
Pass number 4
Now that we know how to loop, we can very easily do something for each of the reviews in the Restaurant class.
NSArray* reviews = [restaurant reviews];
for (int i = 0; i < [reviews count]; i++) {
Review* review = [reviews objectAtIndex:i];
NSLog(@"Review Text: %@", review.text);
}
While that’s helpful, it’s a bunch of code required to effectively say “I want to do something for every review”. That’s where fast enumeration comes in.
Fast enumeration looks like this:
for (Review* review in [restaurant reviews]) {
NSLog(@"Review Text: %@", review.text);
}
We’ll use this whenever we step through an array.
What if you want to do something conditionally? For this, you use an if statement:
if (review.score > 4)
{
NSLog(@"This is a great review");
}
else if (review.score > 2)
{
NSLog(@"This is a mediocre review");
}
else
{
NSLog(@"This is a terrible review");
}
The contents of an if block is only executed if the if statement matches. If it’s followed by an else or an else if statement, that statement will only be executed if the previous if statement fails. In the example above, only one of the 3 options will be executed. For a review with a score of 3, this will output only “This is a mediocre review”. For a review with a score of 1, it will output “This is a terrible review”.
Contrast that with this:
if (review.score > 4)
{
NSLog(@"This is a great review");
}
if (review.score > 2)
{
NSLog(@"This is a mediocre review");
}
if (review.score > 0)
{
NSLog(@"This is a terrible review");
}
Now if your review has a score of 5, it will execute all 3 of the above statements, and the output will be “This is a great review” then “This is a mediocre review” then “This is a terrible review”. Clearly this isn’t the path we want.
When working with if statements, you can put in any statement that evaluates to a BOOL value. Here are a few common operators: <, <=. >, >=, ==, !=, !
Also, you can call any method that would return a BOOL: [@”myString” isEqualToString:@”someOtherString”]
You can also test if a value is nil: myVariable == nil (or myVariable != nil)
Let’s define “most helpful” as the review with the “highest percentage of helpful ratings, with more than 5 helpful ratings”.
Create a method on Review that returns a float of the review’s helpful percentage.
Create a method on Restaurant that returns the most helpful Review object from the reviews array: -(Review*) mostHelpfulReview. Have it return nil if none is available.
Tips:
reviews arrayIn human language, your method should do something like this: 1. Step through all the reviews. 2. For each review, check to see if it has more than 5 helpful ratings 3. If there isn’t yet a best review, set this to be the best review. 4. Otherwise, check to see if it has more than the previous best review. 5. If it does, set that review as the best review and keep looking for a better one. 6. When finished going through all the reviews, return the best one, or nil if there isn’t a best one.
In your DetailViewController class, call your method, and display the best review on the screen instead of review1.
Make sure you hook up both labels.
So far, we’ve created NSStrings and NSArrays, and called methods on them. We haven’t modified their contents, however. The closest we came to modifying a string was when we did this:
ageLabel.text = [NSString stringWithFormat:@"Est. %i (%i years ago)", restaurant.yearOpened, [restaurant age]];
However, we never modified a string there, we simply created one new.
You would think that it would be possible to add to or change an NSString or NSArray. You can’t.
It’s impossible to modify an NSString or NSArray.
But, you must be immediately saying, how would I add a new review to the array?
You have 2 options. First, you can create a new Array, and create that array with the items from the old array and the items from the new array. There are helpful methods on Array to help you do that.
The second way is for when you create an Array that you are going to modify frequently, like adding reviews. For this, you create an NSMutableArray.
NSMutableArray is a subclass of NSArray, meaning that it has all the functionality of NSArray and some of it’s own. Notably, it adds some nifty methods, such as:
[myMutableArray addObject:object];
[myMutableArray removeObjectAtIndex:0];
[myMutableArray insertObject:object atIndex:0];
The same goes for NSString, allowing you to do things such as:
NSMutableString* myMutableString = [[NSMutableString alloc] initWithString:@"One"];
[myMutableString stringByAppendingString:@" Two"];
Make your reviews property mutable.
Add another review you make up to the end of the reviews array using addObject: You should have 5 reviews.
Tips:
reviews is nil. It is NOT an empty array, it simply doesn’t exist, so you can’t add to it.reviews property to be an empty mutable array. Then, only add objects to it rather than replacing it in viewDidLoad.An edge case is when things are not ideal for your program, yet it still has to function. This code has a pretty glaring edge case:
What happens when there are no reviews? What happens when there are reviews, but none of them have enough helpful ratings to show as helpful?
To see this case in action, comment out the lines where you add objects to your array. Alternatively, you could try setting all of the helpfulRatings on all of the reviews to 0.
As you can see, the situation isn’t pretty:

To help with that, we should add an if statement to the spot where we are setting the UILabel’s representing the review. Perhaps we should set the first to something like “Not enough helpful reviews yet”, and set the second to blank.
Modify the code that sets helpfulReviewLabel.text and helpfulReviewPercentageLabel.text to handle this edge case.
Add a method -(float) averageCustomerReview to Restaurant to calculate the average customer review as a float.
You should only need a for loop, an int to hold the total as you sum, and the count method of NSArray. Watch out for integer division vs floating point devision, we want a result like 3.89, not 3.
Using a series of if statements in your viewDidLoad method, change the image of each star to properly reflect the average review.
star1.image = [UIImage imageNamed:@"Star_ON.png"];By understanding Classes, Objects, NSStrings, NSArrays, for loops and if statements, we now have a powerful arsenal of tools at our disposal to handle many different kinds of scenarios in Objective-C.
Now that you know the basics, you can peruse the Apple Developer Library for more neat classes that you can use. I suggest you check out NSString, NSArray, NSMutableArray, and UIImageView.
Due February 27
Note: this assignment was originally due February 20, but we don’t have class that day.
Objective-C is an Object Oriented language, which means that we’ll primarily dealing with objects when writing code. Most of those objects will be those defined by Apple for our assistance, but we’ll also define a few ourselves.
An object is a structure that is held in the computer’s memory that has 2 primary purposes:
Let’s use the physical-world example of a coffee mug.
You can use the tumblr archive feature to better find posts.
Each week, we’ll post a single assignment post to the blog, with a summary of all of the assignments due that week: programming, user experience, reading, etc.
These posts will be tagged “assignment” just like all the other posts that describe the assignments. We’ll review these posts at the end of class.
As for the other assignment posts, we’ll post those throughout the week building up to the class. If this is confusing, please let me know.
To improve clarity, I’ll post the due date at the top of each assignment.
Due February 6

Read these documents for a more in-depth view of the Xcode UI:
Xcode Basics at developer.apple.com
All assignments will be posted to this blog. I’ll post the the assignment before class, and for most of the assignments we will spend time in-class working on the assignment. Some students will complete the entire assignment in class, others will not.
Each assignment will be different, but the parts of the assignment that you are expected to perform will be highlighted in green, like this.
If the green areas include questions that cannot be answered through code (example from Assignment 1: What does %.2f mean?) we’ll be discussing the answer in class, so you don’t need to turn anything in. If that class discussion results in code modifications, you’ll be expected to make those code modifications.
When you see a yellow highlight in a post, it means I’ve gone of on a tangent. It could be a useful tip, a common problem, or simply something I think is interesting that I want to mention at the time.
To complete an assignment, simply commit your code to your forked GitHub repository. Remember to sync the GitHub app so that the code goes up on GitHub.
Your grade for the programming assignments will be based on the following criteria:
If you spend time on the assignments, work through all of the exercises, you will receive full credit on the assignment. Any extra credit performed will be applied to other assignments.
Omnigraffle is good tool, but the high price is a serious detriment to many people.
Here are a couple of free or inexpensive alternatives. Please give them a try and share what you find in the comments.
Mobile Media
PSAM 5152 - A - Spring 2012
Mondays 6-8:40 - 6 E 16th St - Rm 1208
Drew Cogbill
Adjunct Professor
cogbilla@newschool.edu
Twitter: @drewcogbill
Dimitri Stancioff
Adjunct Professor
dstancioff@gmail.com
Twitter: @dstancioff
This class will explore design and development for mobile. To frame this exploration, we will work with Apple’s iOS platform.
The goal of this class is: 1. To encourage students to extend their understanding of UX/interaction design to the mobile space 2. To expose students to basic programming skills and environments used for mobile development.
Students will leave the class able to fluently converse about mobile UX and will have a familiarity with the tools used for commercial iOS design and development (Xcode, beta app distribution, versioning software, etc.) Students will not leave this class as masters of iOS development. They will, however, be poised to continue pursuing their interests in mobile development.
Prerequisites: Students should be familiar with web development (HTML/CSS/JavaScript) and/or C++, Objective-C, or Open Frameworks.