Objectively Speaking 2: A Crash Course in Objective-C for iOS 6

This is the 2nd post by iOS Tutorial Team Member Linda Burke, an indie iOS developer and the founder of canApps. If you are a software developer skilled in another platform, but want to start learning iPhone development (and hence Objective-C) – this is the tutorial series for you! This tutorial picks up where the […] By .

Leave a rating/review
Save for later
Share
You are currently viewing page 5 of 6 of this article. Click here to view the first page.

Adding a New View

You might have noticed that the property list has tips as one of its elements. This is where you implement the ability for the player to call up the “tip” screen and get a tip for the current question.

First, you’ll need to create the methods to keep track of the tip for each clue.

Add the following variables to Quiz.h at the end of the list of @property declarations:

@property (nonatomic, assign) NSInteger tipCount;
@property (nonatomic, strong) NSString * tip;

The first variable keeps track of the number of tips, while the second stores the current tip.

Now you’ll need to initialize tipCount to zero the first time through.

Add the following line to Quiz.m, at the end of the if statement block in initWithQuiz:

self.tipCount = 0;

You’ll also need to reset all the pertinent variables when the user moves on to the next question.

Next modify nextQuestion in Quiz.m as follows:

- (void) nextQuestion: (NSUInteger) idx 
{    
    self.quote = [NSString stringWithFormat:@"'%@'",self.movieArray[idx][@"quote"]];
 
    self.ans1 = self.movieArray[idx][@"ans1"];
    self.ans2 = self.movieArray[idx][@"ans2"];
    self.ans3 = self.movieArray[idx][@"ans3"];
    self.tip = self.movieArray[idx][@"tip"];
     
    if (idx == 0) {
        self.correctCount = 0;
        self.incorrectCount = 0;
        self.tipCount = 0;
    }

}

In the code above, you first obtain the current tip, then set the quiz count to zero when the user is on the first question.

If the user has used up all of their allotted tips, then the tips button should not be available to the player.

To do this, move back to QuoteQuizViewController.m and add the following code to the end of nextQuizItem:

if (self.quiz.tipCount < 3) {
    self.infoButton.hidden = NO;
} else {
    self.infoButton.hidden = YES;
}

Once tipCount exceeds the three allotted tips, then you simply set the button's hidden property to make it unavailable.

Showing the Tips

Now that all of the supporting modules have been created, you'll need to create a view controller to show the requested tips to the player.

To do this, go to File\New File…, choose the iOS\Cocoa Touch Class\Objective-C class template, and click Next. Name the new class QuizTipViewController and make it a subclass of UIViewController. Finally, click Next then Create.

Now you need to add a protocol to QuizTipViewController.h so that this class becomes a delegate.

Add the following code to QuizTipViewController.h just before @interface:

@protocol QuizTipViewControllerDelegate;

A protocol allows classes to share similarly defined behavior. This is helpful when classes are not related to each other, but still behave in similar ways. In this way, classes do not need to "know" about one another, which reduces dependencies throughout your code.

Notice that the protocol has the word "delegate" in it. What's a delegate?

A delegate is an object that performs work on behalf of another object. For example, a foreman delegates the construction of a sidewalk to some of his workers in the same way an object may delegate the processing of information to another object. In this case, the class will notify another object that an event has occurred.

By using delegates with protocols, the delegator need not be concerned with the actual objects that are doing the work — so long as the work gets done! :]

Add the following code to QuizTipViewController.h between @interface and @end:

@property (nonatomic, assign) id <QuizTipViewControllerDelegate> delegate;
@property (weak, nonatomic) IBOutlet UITextView * tipView;
@property (nonatomic, copy) NSString * tipText;

When the user presses the "Done" button, QuizTipViewController will notify its delegate that the user is finished and the tip view should be dismissed. In this case, the delegate is QuizViewController which also is the presenter of QuizTipViewController.

Once QuizViewController is told that the "show is over", it will dismiss QuizTipViewController.

Add the following line of code to QuizTipViewController.h just before @end:

- (IBAction)doneAction:(id)sender;

You're going to add a button that says "Done" on this view controller, and here you're declaring the method that you'll set up to be called when the button is tapped.

Finally, declare the rest of your protocol. While protocols can be contained in their own file, it is also common for developers to define them in the header file of the related class.

Add the following code to QuizTipViewController.h just after @end:

@protocol QuizTipViewControllerDelegate
- (void)quizTipDidFinish:(QuizTipViewController *)controller;
@end

Here you say that any class that implements this protocol must implement one method, quizTipDidFinish:.

Switch to QuizTipViewController.m. At the end of viewDidLoad, add the following code:

self.tipView.text = self.tipText;

This will set the tipText field to the tip that was set in the class variable.

Next, add the following method to QuizTipViewController.m, just before the @end declaration:

- (IBAction)doneAction:(id)sender
{
   [self.delegate quizTipDidFinish:self];
}

Here you tell call the quizTipDidFinish on the delegate method when the button is tapped.

Next, let's make the QuoteQuizViewController implement the delegate.

Switch over to QuoteQuizViewController.h and add the import line for QuizTipViewController.h directly below the import statement for UIKit. Also add <QuizTipViewControllerDelegate> to the end of the @interface declaration to mark it as implementing the protocol, as shown below:

#import <UIKit/UIKit.h>
#import "QuizTipViewController.h"

@class Quiz;
@interface QuoteQuizViewController : UIViewController <QuizTipViewControllerDelegate>

@property (nonatomic, assign) NSInteger quizIndex;
@property (nonatomic, strong) Quiz * quiz;

- (IBAction)ans1Action:(id)sender;
- (IBAction)ans2Action:(id)sender;
- (IBAction)ans3Action:(id)sender;
- (IBAction)startAgain:(id)sender;

@end

Open QuoteQuizViewController.m and create quizTipDidMethod — as defined by the protocol — by adding the code below just before the final @end:

- (void)quizTipDidFinish:(QuizTipViewController *) controller {
    [self dismissViewControllerAnimated:YES completion:^{}];
}

So when the user taps the done button, this delegate method gets called, and all you do is dismiss the view controller. You could do some more fancy work here if you wanted, like saving data.

Now it's time to add this new view controller to your user interface. Open the MainStoryboard.storyboard and drag in a new view controller, as shown in the screenshot below:

Add a new view controller

Select the new view controller and switch to the Identity Inspector (the third tab in). Under the Custom Class section, set the class field to be QuizTipViewController, as shown below:

Changing the class

Drag a label onto the view and place it near the top of the screen. Double-click the label and modify the label's text to be "Movie tip (3 tips only)". Center the label in the middle of the view.

Now drag in a textview under the label. Set the width to be 280 points, and the height to be 136 points.

Place a button underneath the textview, and make it the same width as the textview. Modify the text of the button to read "Done".

Your interface should now look like the following:

TipViewAdded

Right-click the Quiz Tip View Controller Scene, drag it to the text view, and then select the tipView outlet. Next, right-click the Done button, drag it to the Quote Tip View Controller, and select doneAction.

Now it is time to link up the two view controllers using a segue. First you will need a tip button — this will be the button that triggers the app to show the quiz tip view.

Scroll over to the previous view controller and select the "Next" button. Copy and paste the Next button, and drag this new button to the left side of the view controller. Modify the button's text to read Tip.

AddingTipButton

Since you copied the button, you also copied the actions associated with it. Right click the button, and click the 'X' button next to the action associated with "Touch Up Inside" action, to remove the action, as shown below:

Delete action

We could have just dragged in a new button, but this is a common problem to run across so I wanted to show you it.

Finally, right-click Quote Quiz View Controller, drag over to the tip button, then select the infoButton outlet.