How to Control the View in Your iPad App - dummies

How to Control the View in Your iPad App

By Neal Goldstein, Tony Bove

When creating your iPad app, you need to include code that controls the view in that app. The following example iPad app is designed to display words scrolling down the screen. After opening the DeepThoughtsViewController.m file so that it appears in the Text editor, you’d insert the code in bold (the code that’s not in bold is supplied by the View-Based Application template):

#import "DeepThoughtsViewController.h"
#import "Constants.h"
@implementation DeepThoughtsViewController
@synthesize speed, imageView;
#pragma mark -
#pragma mark View life cycle
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    return self;
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
- (void)viewDidLoad {
  [super viewDidLoad];
  [NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
  if (![[NSUserDefaults standardUserDefaults] objectForKey:kWordsOfWisdom]) {
    [[NSUserDefaults standardUserDefaults]setObject:@"Peace Love Groovy Music" forKey:kWordsOfWisdom];
    fallingWords = @"Peace Love Groovy Music";
  else {
    fallingWords = [[NSUserDefaults standardUserDefaults] stringForKey:kWordsOfWisdom];
  if (![[NSUserDefaults standardUserDefaults] objectForKey:kSpeed] ){
    [[NSUserDefaults standardUserDefaults]setDouble:10.0 forKey:kSpeed]; 
    speed = kMaxSpeed-10.0;} 
  else {
    speed = kMaxSpeed-[[NSUserDefaults standardUserDefaults] doubleForKey:kSpeed] ;
#pragma mark -
#pragma mark Animation
- (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  clearColor]; 
  fallingImageView.adjustsFontSizeToFitWidth = YES;
  int startX = round(random() % 400);
  int endX =  round(random() % 400);
  //speed of falling
  double randomSpeed = (1/round(random() % 100) +1) *speed;
  // image size;
  double scaleH = (1/round(random() % 100) +1) *60;
  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, self.view.frame.size.height, scaleW, scaleH);
  [UIView commitAnimations];
-(void)animationDone:(NSString *)animationID finished:(NSNumber *)finished context:(id)context {
  UIImageView *fallingImageView = context;
  [fallingImageView removeFromSuperview];
  [fallingImageView release];
#pragma mark -
#pragma mark Controls
- (IBAction)settings {    
#pragma mark -
#pragma mark Orientation
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
#pragma mark -
#pragma mark Memory Management
- (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];

Here’s a breakdown of the code you add:

  • The first statement you add imports the Constants.h file. You can now use any keys you set up with NSUserDefaults in the subsequent code to retrieve the user settings.

  • Objective-C creates the accessor methods you need for you whenever you include an @synthesize statement; the statement in the preceding code creates an accessor method for each @property declaration (speed and imageView).

  • The two # pragma mark statements contain the initialization and load-view code.

  • The viewDidLoad message is sent right after the view has been loaded from the nib file (the .xib file you can modify in Interface Builder). This is the place where you insert your code for view initialization, which in this case means displaying DeepThoughts’ falling words. The viewDidLoad method you inserted starts out by setting up a timer for the interval between each display of falling words.

    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. This code uses 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.

  • Next, the code checks to see whether the kWordsOfWisdom setting has been moved into NSUserDefaults.

  • The code moves the user’s preferences into NSUserDefaults only after the application runs for the first time. If the settings have not been moved into NSUserDefaults yet, the code uses the initial preference value (“Peace Love Groovy Music”) for fallingWords. If the settings have been moved into NSUserDefaults, the code reads them in and then sets fallingWords to whatever the user’s preference is. The code then repeats this check with the speed setting.

    You use standardUserDefaults (an NSUserDefaults class method) to gain access to the standard user default settings, and you can store data there.

  • The #pragma mark section titled Controls includes the placeholder settings method for connecting the Light Info button to the view controller. This is the action method using the IBAction qualifier.

  • Connecting the timer to the actual drawing of the display is the onTimer method. 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 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.

  • 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, which uses removeFromSuperview (an instance method of the UIView class) to remove fallingImageView and then uses release (an instance method of the NSAutoreleasePool class) to release fallingImageView.

  • Finally, this code has two # pragma mark statements to mark the section as Orientation and two more # pragma mark statements above the didReceiveMemoryWarning method to mark that section as Memory Management.