Chapter 3. Developing the Main View

In This Chapter

  • Using your friendly Xcode Text editor

  • Adding your code to the Main view controller

  • Creating animation in the Main view

I wanted to keep this example iPhone utility app as simple as possible so that you can focus on how it works as an app in the iPhone OS — and you can then go off and design your complex app. The Utility Application template creates the skeleton for a fully functioning iPhone app (DeepThoughts) — and now you get to flesh it all out with some code that transforms it from an app that just sits there and looks pretty to an app that actually does something.

DeepThoughts is supposed to display "falling" words — text flowing down the Main view in different sizes, starting with the words "Peace Love Groovy Music" — at a specified time interval and at a speed the user can change. DeepThoughts should also allow the user to enter text in the Flipside view to substitute different words for "Peace Love Groovy Music" and, eventually, to select a photo from the iPhone's photo library to substitute for the words.

As you add the code to DeepThoughts, I also explain some of the features of the Xcode Text editor.

Using the Xcode Text Editor

The main tool you use to write code for an iPhone application is the Xcode Text editor. Apple has gone out of its way to make the Text editor as user-friendly as possible, as evidenced by the following list of (quite convenient) features:

  • Code Sense: Code Sense is a feature of the editor that shows arguments, placeholders, and suggested code as you type statements. Code Sense can be really useful, especially if you're like me and forget exactly what the arguments for a function actually are. When Code Sense is active (it is by default), Xcode uses the text you typed, as well as the context within which you typed it, to provide suggestions for completing what it thinks you're going to type. You can accept suggestions by pressing Tab or Return. You may also display a list of completions by pressing the Escape key. You can set options for Code Sense by choosing Xcode

    Using the Xcode Text Editor
  • Code folding in the focus ribbon: With code folding, you can collapse code that you're not working on and display only the code that requires your attention. You do this by clicking in the Focus Ribbon column to the left of the code you want to hide (right there between the gutter, which displays line numbers and breakpoints, and the editor) to show a disclosure triangle. Clicking the disclosure triangle hides or shows blocks of code.

  • Switching between header and implementation windows: On the toolbar above the Text editor, you click the last icon before the lock to switch from the .h (header) file to the .m (implementation) file, and vice versa. While the header declares the class's instance variables and methods, the implementation holds the logic of your code. If you look inside the MainView and FlipsideView sections of the Groups & Files list in the Project window, you can see the separate .h and .m files for the Main and Flipside view classes.

  • Launching a file in a separate window: Double-click the filename to launch the file in a new window. If you have a big monitor, or multiple monitors, this new window enables you to look at more than one file at a time. You can, for example, look at the method of one class and the method it invokes in the same class or even a different class.

Accessing Documentation

Like many developers, you may find yourself wanting to dig deeper when it comes to a particular bit of code. That's when you'll really appreciate Xcode's Quick Help, header file access, Documentation window, Help menu, and Find tools. With these tools, you can quickly access the documentation for a particular class, method, or property.

To see how this works, say you have the Project window open with the code displayed in Figure 3-1. What if you wanted to find out more about UIApplicationDelegate?

Quick Help

Quick Help is an unobtrusive window that provides the documentation for a single symbol. It pops up inline, although you can use Quick Help as a symbol inspector (which stays open) by moving the window after it opens. You can also customize the display in Documentation preferences in Xcode preferences.

To get Quick Help for a symbol, double-click to select the symbol in the Text editor (in this case UIApplicationDelegate; see Figure 3-1) and then choose Help

Quick Help
Getting Quick Help.

Figure 3-1. Getting Quick Help.

The header file for a symbol

Headers are a big deal in code because they're the place where you find the class declaration, which includes all of its instance variables and method declarations. To get the header file for a symbol, press

The header file for a symbol

Tip

This trick works for the classes you create as well.

Documentation window

The Documentation window lets you browse and search items that are part of the Apple Developer Connection Reference Library (a collection of developer documentation and tech notes) as well as any third-party documentation you have installed.

You access the documentation by pressing

Documentation window
The header file for UIApplicationDelegate.

Figure 3-2. The header file for UIApplicationDelegate.

The Documentation window.

Figure 3-3. The Documentation window.

Using the Documentation window, you can browse and search the developer documentation — the API references, guides, and article collections about particular tools or technologies — installed on your computer. It's the go-to place for getting documentation about a method or more info about the methods and properties in a framework class.

Help menu

The Help menu's search field also lets you search Xcode documentation as well as open the Documentation window and Quick Help.

You can also right-click on a symbol and get a pop-up menu that gives you similar options to what you see in the Help menu, including Quick Help (and other related functions).

Find

Xcode can also help you find things in your own project. The submenu that you access by choosing Edit

Find

You'll find that, as your classes get bigger, sometimes you'll want to find a single symbol or all occurrences of a symbol in a file or class. You can easily do that by choosing Edit

Find
Finding viewDidLoad in a file.

Figure 3-4. Finding viewDidLoad in a file.

If you select an item in the top pane of the editor, as you can see in Figure 3-4, the file in which that instance occurs is opened in the bottom pane of the editor and the reference highlighted.

You can also use Find to go through your whole project by choosing Edit

Finding viewDidLoad in a file.

Your searches are saved in your project. Click the triangle next to Find Results in the Groups & Files list to reveal your searches, as shown in Figure 3-6. Select a search to see the search results.

Now that you have some idea of how to use the Xcode Text editor, it's time to write some code.

Project Find.

Figure 3-5. Project Find.

Revisiting your searches, which are saved in your project.

Figure 3-6. Revisiting your searches, which are saved in your project.

Where Does Your Code Go?

One of the biggest challenges facing a developer working with an unfamiliar framework and template is figuring out where in the control flow — the sequence in which messages are sent during execution — to put the code to get something done.

The delegate object

As you may recall from Chapter 1 of this minibook, UIApplication loads the parts of the MainWindow.xib to create DeepThoughtsAppDelegate and the window, and sends DeepThoughtsAppDelegate the applicationDidFinishLaunching: message. The applicationDidFinishLaunching: method in DeepThoughtsAppDelegate initializes MainView.

The applicationDidFinishLaunching: message is sent at the very beginning, before the user can even see anything on the screen. Here's where you'd insert your code to initialize your application — where you'd load data, for example, or restore the state of the application to where it was the last time the user exited.

The controller object

MainViewController is the controller responsible for managing MainView. If you look at the code in MainViewController.m (as shown in Chapter 2 of this minibook), you see the following commented-out code:

/*
 // Implement viewDidLoad to do additional setup after
   loading the view, typically from a nib.
 - (void)viewDidLoad {
[super viewDidLoad];
}
*/

The viewDidLoad message is sent right after the view has been loaded from the nib file — check out Chapter 1 of this minibook for a complete explanation of that loading process. This is the place where you insert your code for view initialization, which in this case means displaying the DeepThoughts' falling words.

Tip

Although I don't use it in this example, you could also make use of the viewWillAppear message, which is sent right before the view will appear. This would be the place to insert your code to do anything needed before the view becomes visible. Both viewDidLoad and viewWillAppear are methods declared in the UIViewController class and are invoked at the appropriate times by the framework.

Creating an Animated View

To add the code you need to display the falling words at speed that could be set by the user, first open MainViewController.h and insert the code in bold in Listing 3-1.

Example 3-1. MainViewController.h

#import "FlipsideViewController.h"

@interface MainViewController : UIViewController
   <FlipsideViewControllerDelegate> {
  UIImage *fallingImage;
  NSString *fallingWords;
  double    speed;
}
- (IBAction)showInfo;
@end

This establishes the falling image itself (fallingImage), which will contain the text string in fallingWords and will flow down the display according to the speed.

Next, open MainViewController.m and insert the code in bold in Listing 3-2, which replaces the commented-out code described previously.

Example 3-2. MainViewController.m

#import "MainViewController.h"
#import "MainView.h"

@implementation MainViewController

-  (id)initWithNibName:(NSString *)nibNameOrNil
    bundle:(NSBundle *)nibBundleOrNil {
     if (self = [super initWithNibName:nibNameOrNil
    bundle:nibBundleOrNil]) {
        // Custom initialization
     }
     return self;

}

-  (void)viewDidLoad {

   [super viewDidLoad];
   self.view.backgroundColor = [UIColor colorWithRed:.5
    green:3 blue:.7 alpha:1];}
[NSTimer scheduledTimerWithTimeInterval:.5 target:self
    selector:@selector(onTimer) userInfo:nil repeats:YES];

   fallingWords = [[NSString alloc] initWithString:@"Peace
    Love Groovy Music"];
   speed = 10.0;
}

- (void)onTimer{

  UILabel *fallingImageView = [[UILabel alloc]
    initWithFrame:CGRectMake(0, 0, 100, 30)];
  fallingImageView.text = fallingWords;
  fallingImageView.textColor = [UIColor  purpleColor];
  fallingImageView.font = [UIFont systemFontOfSize:30];
  fallingImageView.backgroundColor = [UIColor
    colorWithRed:.5 green:3 blue:.7 alpha:1];
  fallingImageView.adjustsFontSizeToFitWidth = YES;

  int startX = round(random() % 80);
  int endX =  round(random() % 80);
  //speed of falling
  double randomSpeed = (1/round(random() % 100) +1) *speed;
  // image size;
  double scaleH = (1/round(random() % 100) +1) *30;
  double scaleW = (1/round(random() % 100) +1) *200;

  [self.view addSubview:fallingImageView];

  fallingImageView.frame = CGRectMake(startX, −100, scaleW,
   scaleH);

  fallingImageView.alpha = .75;

  [UIView beginAnimations:nil context:fallingImageView];
  [UIView setAnimationDuration:randomSpeed];
  [UIView setAnimationDelegate:self];
       [UIView
   setAnimationDidStopSelector:@selector(
   animationDone:finished:context:)];

  fallingImageView.frame = CGRectMake(endX, 500, scaleW,
   scaleH);

  [UIView commitAnimations];
}

-(void)animationDone:(NSString *)animationID
   finished:(NSNumber *)finished context:(id)context {
  UIImageView *fallingImageView = context;
  [fallingImageView removeFromSuperview];
  [fallingImageView release];
}
/*
  // Override to allow orientations other than the default
    portrait orientation.
  - (BOOL)shouldAutorotateToInterfaceOrientation:(
           UIInterfaceOrientation)interfaceOrientation {
  // Return YES for supported orientations
  return (interfaceOrientation ==
    UIInterfaceOrientationPortrait);
  }
  */

- (void)flipsideViewControllerDidFinish:(FlipsideViewControl
   ler *)controller {

   [self dismissModalViewControllerAnimated:YES];
}

- (IBAction)showInfo {

   FlipsideViewController *controller
   = [[FlipsideViewController alloc]
   initWithNibName:@"FlipsideView" bundle:nil];
   controller.delegate = self;

   controller.modalTransitionStyle =
   UIModalTransitionStyleFlipHorizontal;
   [self presentModalViewController:controller animated:YES];

   [controller release];
}

/*
 // Override to allow orientations other than the default
    portrait orientation.
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceO
   rientation {
// Return YES for supported orientations
return (interfaceOrientation ==
  UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
   // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

   // Release any cached data, images, etc that aren't in
   use.
}
- (void)viewDidUnload {
   // Release any retained subviews of the main view.
   // e.g. self.myOutlet = nil;
}

- (void)dealloc {
    [super dealloc];
}

@end

The viewDidLoad method

The first chunk of code to examine (in bold in Listing 3-2) changes the background color of the Main view and sets up a timer for the interval between each display of falling words or images:

- (void)viewDidLoad {

  [super viewDidLoad];
  self.view.backgroundColor = [UIColor colorWithRed:.5
   green:3 blue:.7 alpha:1];
  [NSTimer scheduledTimerWithTimeInterval:.5 target:self
   selector:@selector(onTimer) userInfo:nil repeats:YES];

  fallingWords = [[NSString alloc] initWithString:@"Peace
   Love Groovy Music"];
  speed = 10.0;
}

The viewDidLoad method enables you to change the background color. A UIColor object represents color and sometimes opacity (alpha value). The colorWithRed:.5 green:3 blue:.7 alpha:1 creates and returns a color object using the specified opacity and RGB component values.

You use the NSTimer class to create timers. A timer waits until a certain time interval has elapsed and then fires, sending a specified message to a target object. I use the scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: class method to create the timer and schedule it on the current run loop in the default mode. The interval is 0.5 seconds, the target is self, and the selector is the message to send to the target when the timer fires — in this case, onTimer. The userInfo is the user info for the timer (set to nil), and the timer is set to repeat — that is, it will repeatedly reschedule itself until invalidated.

An NSString object represents a character string. Representing strings as objects allows you to use strings wherever you use other objects. It also provides the benefits of encapsulation, so that string objects can use whatever encoding and storage are needed for efficiency while simply appearing as arrays of characters. In this case, fallingWords is initialized with the string "Peace Love Groovy Music". The speed is initialized with the value 10.

Drawing the view

Connecting the timer to the actual drawing of the display is the onTimer method. Take a good look at the code for this method (from the bold code in Listing 3-2):

- (void)onTimer{

  UILabel *fallingImageView = [[UILabel alloc]
   initWithFrame:CGRectMake(0, 0, 100, 30)];
  fallingImageView.text = fallingWords;
  fallingImageView.textColor = [UIColor purpleColor];
  fallingImageView.font = [UIFont systemFontOfSize:30];
  fallingImageView.backgroundColor = [UIColor
    colorWithRed:.5 green:3 blue:.7 alpha:1];
  fallingImageView.adjustsFontSizeToFitWidth = YES;

  int startX = round(random() % 80);
  int endX = round(random() % 80);
  //speed of falling
  double randomSpeed = (1/round(random() % 100) +1) *speed;
  // image size;
  double scaleH = (1/round(random() % 100) +1) *30;
  double scaleW = (1/round(random() % 100) +1) *200;

  [self.view addSubview:fallingImageView];

  fallingImageView.frame = CGRectMake(startX, −100, scaleW,
   scaleH);

  fallingImageView.alpha = .75;

  [UIView beginAnimations:nil context:fallingImageView];
  [UIView setAnimationDuration:randomSpeed];
  [UIView setAnimationDelegate:self];
       [UIView
   setAnimationDidStopSelector:@selector(
   animationDone:finished:context:)];

  fallingImageView.frame = CGRectMake(endX, 500, scaleW,
   scaleH);

  [UIView commitAnimations];
}
-(void)animationDone:(NSString *)animationID
 finished:(NSNumber *)finished context:(id)context {
UIImageView *fallingImageView = context;
[fallingImageView removeFromSuperview];
[fallingImageView release];
}

The UILabel class implements a read-only text view. You can use this class to draw one or multiple lines of static text. In this case, the block of code uses the initWithFrame method with CGRectMake to create a rectangle, with the x-coordinate and y-coordinate of the rectangle's origin point at (0, 0) and a specified width and height (100, 30).

The code converts the fallingWords string to fallingImageView for display; sets up the text color, font, and background color; and adjusts the font size for the width. The font and textColor properties apply to the entire text string.

The next block of code uses the random function for the starting and ending points (startX and endX), for speed, and for width (scaleW) and height (scaleH) for fallingImageView. The random function uses a non-linear additive-feedback random number generator, with a default table of size 31 long integers, and returns successive pseudo-random numbers in the range from 0 to 2,147,483,647. Then, addSubview adds a view so that it's displayed above its siblings, and frame specifies the rectangle in the super-layer's coordinate space, using startX, −100, scaleW, and scaleH.

The animation block

The UIView class provides common methods you use to create all types of views. In this particular code, it's used for a block of animation. The beginAnimations:context: method starts the animation block, and the commitAnimations method ends the block. Inside the block, the code sets property values to make visual changes that comprise the animation. In this case, the code changes the rectangle's starting coordinates from startX to endX, and from −100 to 500:

fallingImageView.frame = CGRectMake(endX, 500, scaleW,
   scaleH);

The setAnimationDuration method sets the animation duration, and setAnimationDidStopSelector sets the message to send to the animation delegate when animation stops. The animation delegate is animationDone, uses removeFromSuperview (an instance method of the UIView class) to remove fallingImageView from its superview, its window, and from the responder chain; and then uses release (an instance method of the NSAutoreleasePool class) to release fallingImageView. Remember, you own any object you create with alloc, which means you're responsible for releasing it when you're done.

Testing the Main View

Save your Xcode project by choosing File

Testing the Main View
The Main view of the app in the iPhone Simulator.

Figure 3-7. The Main view of the app in the iPhone Simulator.

The animation is quite impressive, but now is not the time to sit on your laurels. There's more work to be done — setting up the Flipside view controls so that users can change the text and speed, and saving the user's preferences. All that and more are covered in Chapter 4 of this minibook.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.20.133