Chapter 4
|
Modified: |

Downloads
iPhone SDK Development examples - http://pragprog.com/titles/amiphd
Resources
See the text, on page 73, for detailed instructions on the ModelEditViewController, presented later.
Overview
The text presents a ViewController, MovieViewController, to display three UILabel and a UIButton.
No interaction is implemented, only display of the UILabel content when the the application view is displayed.
MovieViewController
Key points:
- inherits from UIViewController,
- -viewDidLoad delegate used to initialize view controller objects, here a new Movie object,
- -viewWillAppear delegate used to refresh display, necessary when switching between views.
- @property(nonatomic, retain) UILabel *titleLabel; defines instance variable getter/setter semantics; not thread-safe, release old object, retain new object in setter.
- self.titleLabel = nil; in dealloc, the setter releases old object and sets new object to nil.
- self.titleLabel.text = self.movie.title; getter/setter could also be written as:
[titleLabel setText: [movie title]];
- IBOutlet objects have corresponding UILabel defined in the IB for MovieViewController.xib
#import <Foundation/Foundation.h>
@interface Movie : NSObject {
NSString *title;
NSNumber *boxOfficeGross;
NSString *summary;
}
- (id)initWithTitle:(NSString *)newTitle
boxOfficeGross:(NSNumber *)newBoxOfficeGross
summary:(NSString *)newSummary;
@property(nonatomic, copy) NSString *title;
@property(nonatomic, copy) NSNumber *boxOfficeGross;
@property(nonatomic, copy) NSString *summary;
@end
|
#import "Movie.h"
@implementation Movie
@synthesize title;
@synthesize boxOfficeGross;
@synthesize summary;
- (id)initWithTitle:(NSString *)newTitle
boxOfficeGross:(NSNumber *)newBoxOfficeGross
summary:(NSString *)newSummary {
self = [super init];
if(nil != self) {
self.title = newTitle;
self.boxOfficeGross = newBoxOfficeGross;
self.summary = newSummary;
}
return self;
}
- (void) dealloc { // Setter's release
self.title = nil;
self.boxOfficeGross = nil;
self.summary = nil;
[super dealloc];
}
@end
|
#import <UIKit/UIKit.h> @class Movie;
@interface MovieViewController :
UIViewController {
Movie *movie;
UILabel *titleLabel;
UILabel *boxOfficeGrossLabel;
UILabel *summaryLabel;
}
@property(nonatomic, retain)
Movie *movie;
@property(nonatomic, retain)
IBOutlet UILabel *titleLabel;
@property(nonatomic, retain)
IBOutlet UILabel *boxOfficeGrossLabel;
@property(nonatomic, retain)
IBOutlet UILabel *summaryLabel;
- (IBAction)edit; @end |
#import "MovieViewController.h" #import "Movie.h" @implementation MovieViewController @synthesize titleLabel; @synthesize boxOfficeGrossLabel; @synthesize summaryLabel; @synthesize movie; - (IBAction)edit {
NSLog(@"edit method invoked");
}
- (void)viewDidLoad {
[super viewDidLoad];
Movie *newMovie = [[Movie alloc]
initWithTitle:@"Iron Man"
boxOfficeGross:
[NSNumber numberWithFloat:650000000.00]
summary:@"Smart guy makes cool armor"];
self.movie = newMovie;
[newMovie release];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.titleLabel.text = self.movie.title;
NSNumberFormatter *formatter =
[[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
self.boxOfficeGrossLabel.text =
[formatter stringFromNumber:self.movie.boxOfficeGross];
[formatter release];
self.summaryLabel.text = self.movie.summary;
}
- (void)dealloc {
self.titleLabel = nil;
self.boxOfficeGrossLabel = nil;
self.summaryLabel = nil;
self.movie = nil;
[super dealloc];
}
@end
|
Refactoring MovieViewController to Add Editing in a Subview
The MovieViewController will be be refactored for the Edit button to open another view controller, MovieEditViewController.
When MovieEditViewController is exited, the MovieViewController is displayed with any changes.
| MovieViewController
|
MovieEditorViewController
|
A Movie object is accessed in common by the MovieViewController and MovieEditorViewController objects via an alias held in instance variable.
@interface MovieViewController : UIViewController {
Movie *movie;
UILabel *titleLabel;
UILabel *boxOfficeGrossLabel;
UILabel *summaryLabel;
MovieEditorViewController *editingViewController;
}@interface MovieEditorViewController :
UIViewController{
UITextField *titleField;
UITextField *boxOfficeGrossField;
UITextField *summaryField;
Movie *movie;
}Key points in MovieViewController:
IBOutlet MovieEditorViewController *editingViewController added instance variable to MovieEditorViewController created in IB.
-edit method connected to Edit button.
-edit method calls MovieEditorViewController setter, setting Movie instance variable.
-edit method opens the MovieEditorViewController view by:
presentModalViewController
-viewWillAppear displays Movie object edited in MovieEditorViewController.
#import "MovieViewController.h" #import "MovieEditorViewController.h" #import "Movie.h" @implementation MovieViewController @synthesize titleLabel; @synthesize boxOfficeGrossLabel; @synthesize summaryLabel; @synthesize movie; @synthesize editingViewController; - (IBAction)edit {
self.editingViewController.movie = self.movie; // Alias Movie object
[self presentModalViewController:self.editingViewController
animated:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
Movie *newMovie = [[Movie alloc]
initWithTitle:@"Iron Man"
boxOfficeGross:[NSNumber
numberWithFloat:650000000.00]
summary:@"Smart guy makes cool armor"];
self.movie = newMovie;
[newMovie release];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.titleLabel.text = self.movie.title;
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
self.boxOfficeGrossLabel.text =
[formatter stringFromNumber:self.movie.boxOfficeGross];
[formatter release];
self.summaryLabel.text = self.movie.summary;
}
- (void)dealloc {
self.titleLabel = nil;
self.boxOfficeGrossLabel = nil;
self.summaryLabel = nil;
self.movie = nil;
[super dealloc];
}
@end
|
#import <UIKit/UIKit.h> @class Movie;
@class MovieEditorViewController;
@interface MovieViewController : UIViewController {
Movie *movie;
UILabel *titleLabel;
UILabel *boxOfficeGrossLabel;
UILabel *summaryLabel;
MovieEditorViewController *editingViewController;
}
@property(nonatomic, retain)
Movie *movie;
@property(nonatomic, retain)
IBOutlet UILabel *titleLabel;
@property(nonatomic, retain)
IBOutlet UILabel *boxOfficeGrossLabel;
@property(nonatomic, retain)
IBOutlet UILabel *summaryLabel;
@property(nonatomic, retain)
IBOutlet MovieEditorViewController *editingViewController;
- (IBAction)edit;
@end
|
MovieEditViewController
Key points in MovieEditViewController:
-viewWillAppear method displays values of Movie object set by MovieViewController.
MovieEditViewController view closed and MovieViewController displayed by:
- (IBAction)done { [[self parentViewController] dismissModalViewControllerAnimated:YES]; } -textFieldDidEndEditing formats the edited text.
#import "MovieEditorViewController.h"
#import "Movie.h"
@implementation MovieEditorViewController
@synthesize titleField;
@synthesize boxOfficeGrossField;
@synthesize summaryField;
@synthesize movie;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.titleField.text = self.movie.title;
self.summaryField.text = self.movie.summary;
NSNumberFormatter *formatter =
[[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
self.boxOfficeGrossField.text =
[formatter stringFromNumber:self.movie.boxOfficeGross];
[formatter release];
}
- (IBAction)done {
[[self parentViewController]
dismissModalViewControllerAnimated:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
if(textField == self.titleField) {
self.movie.title = self.titleField.text;
} else if(textField == self.boxOfficeGrossField) {
NSNumberFormatter *formatter =
[[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
self.movie.boxOfficeGross =
[formatter numberFromString:self.boxOfficeGrossField.text];
[formatter release];
} else if(textField == self.summaryField) {
self.movie.summary = self.summaryField.text;
}
}
- (void)dealloc {
[super dealloc];
}
@end
|
#import <UIKit/UIKit.h>
|