1. Trang chủ >
  2. Công Nghệ Thông Tin >
  3. Kỹ thuật lập trình >

8  Incorporating and Using Models in the GUI

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (8.37 MB, 640 trang )


static MyWorld



*sharedInstance = nil;



- (id) init {

self = [super init];

if (self != nil){

/* Do NOT allocate/initialize other objects here

that might use the MyWorld's sharedInstance as

that will create an infinite loop */

}

return(self);

}

- (void) initializeSharedInstance{

/* Allocate/initialize your values here as we are

sure this method gets called only AFTER the

instance of MyWorld has been created through

the [sharedInstance] class method */

}

+ (MyWorld *)

sharedInstance{

@synchronized(self){

if (sharedInstance == nil){

sharedInstance = [[self alloc] init];

/* Now initialize the shared instance */

[sharedInstance initializeSharedInstance];

}

return(sharedInstance);

}

}

- (NSUInteger) retainCount{

return(NSUIntegerMax);

}

- (void) release{

/* Don't call super here. The shared instance should

not be deallocated */

}

- (id) autorelease{

return(self);

}

- (id) retain{

return(self);

}



2.8 Incorporating and Using Models in the GUI | 51



www.it-ebooks.info



- (void) dealloc {

[super dealloc];

}

@end



In your views and view controllers or other nonmodel objects, you can retrieve an

instance to your model using the sharedInstance class method of MyWorld:

- (void)viewDidLoad {

[super viewDidLoad];

MyWorld *bigWorld = [MyWorld sharedInstance];

MyWorld *theSameWorld = [MyWorld sharedInstance];

if ([bigWorld isEqual:theSameWorld] == YES){

NSLog(@"The Big World and the Same World are the same!");

} else {

NSLog(@"These two worlds are different.");

}

}



Both bigWorld and theSameWorld now point to the same instance in memory. This is

one of the reasons you might consider creating a shared instance—or what is traditionally called a singleton—whenever you are designing a model or storage of some type

that has to be accessed from multiple objects across a project and you do not want to

keep a reference to the same instance of the object anywhere specific. Using a class

method providing you with a shared instance of an object, you will easily be able to

call this method anywhere using only the name of your class, as shown previously, in

order to obtain a reference to the one and only copy of this object in memory.

A shared instance of an object has a retain count of 1 and should not,

in any circumstances, be retained since that will impose complications

on how the shared instance is maintained.



If you had a good look at the implementation of MyWorld, you must have noticed the

comments in the init and initializeSharedInstance methods. The reason we should

not allocate and initialize important resources in the init method of MyWorld is that if

any of the classes that might be allocated and initialized in the init method of

MyWorld access the sharedInstance method of MyWorld, the sharedInstance class method

will be called prematurely without having already returned from its previous init

method. Therefore, we will be in an infinite loop of calling the sharedInstance

class method since none of the sharedInstance class methods can complete without

depending on another sharedInstance call. This can be demonstrated better with an

example:



52 | Chapter 2: Implementing Controllers and Views



www.it-ebooks.info



1. A view controller calls the sharedInstance class method of MyWorld for the first time

in our application. We have not called this class method anywhere else yet.

2. The sharedInstance class method determines that the sharedInstance static variable is nil, and therefore attempts to allocate and initialize this static variable by

calling the alloc and init methods of the MyWorld object.

3. Imagine we instantiate an object of some type in the init instance method of

MyWorld, by calling the alloc and init methods of that object. Now imagine that

that object’s init method attempts to initialize itself using a variable that is inside

MyWorld. Therefore, the object will call the sharedInstance class method of

MyWorld to get a reference to MyWorld. However, the problem here is that we are

still not out of the init instance method of MyWorld explained in step 2. We are still

trying to finish the init method, but the initialization of our new object was in the

init method and needs to be finished, and since this new initialization depends on

MyWorld itself, another sharedInstance class method will be called and MyWorld will

be allocated and initialized again. Another initialization means an infinite loop to

steps 2 and 3, until the end of time!

To demonstrate this fragile fact, change the init instance method of MyWorld to the

following implementation:

- (id) init {

self = [super init];

if (self != nil){

/* Do NOT allocate/initialize other objects here

that might use the MyWorld's sharedInstance as

that will create an infinite loop */

[MyWorld sharedInstance];

}

return(self);

}



Now if you try to run your application, it will crash. To fix this issue, add the code

shown in bold to the initializeSharedInstance instance method:

- (void) initializeSharedInstance{

/* Allocate/initialize your values here as we are

sure this method gets called only AFTER the

instance of MyWorld has been created through

the [sharedInstance] class method */

[MyWorld sharedInstance];

}



2.8 Incorporating and Using Models in the GUI | 53



www.it-ebooks.info



+ (MyWorld *)

sharedInstance{

@synchronized(self){

if (sharedInstance == nil){

sharedInstance = [[self alloc] init];

/* Now initialize the shared instance */

[sharedInstance initializeSharedInstance];

}

return(sharedInstance);

}

}



2.9 Implementing Navigation Bars

Problem

You want to be able to present options to your users and maintain a stack-like array of

screens that users can traverse easily.



Solution

Use a UINavigationController class to organize the hierarchy of view controllers in your

application. A navigation controller will create a navigation bar for you automatically:

#import

@class ViewsAndVCViewController;

@interface ViewsAndVCAppDelegate : NSObject

{

@public

UIWindow *window;

UINavigationController *navigationController;

}

@property (nonatomic, retain)

IBOutlet UIWindow *window;

@property (nonatomic, retain)

UINavigationController *navigationController;

@end



As you can see, we have declared our navigation controller in our application delegate.

You do not have to do this in the application delegate. In fact, you can instantiate an

object of type UINavigationController anywhere in your application. We will now implement the application delegate:

#import "ViewsAndVCAppDelegate.h"

#import "FirstViewController.h"

@implementation ViewsAndVCAppDelegate



54 | Chapter 2: Implementing Controllers and Views



www.it-ebooks.info



@synthesize window;

@synthesize navigationController;

- (BOOL) application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// Override point for customization after application launch.

FirstViewController *controller =

[[FirstViewController alloc]

initWithNibName:@"FirstViewController"

bundle:nil];

UINavigationController *theNavigationController =

[[UINavigationController alloc]

initWithRootViewController:controller];

self.navigationController = theNavigationController;

[theNavigationController release];

[self.navigationController setNavigationBarHidden:NO

animated:YES];

[controller release];

// Add the view controller's view to the window and display.

[window addSubview:self.navigationController.view];

[window makeKeyAndVisible];

}



return YES;



- (void)dealloc {

[navigationController release];

[window release];

[super dealloc];

}

@end



Discussion

There are two good ways to create navigation controllers in an application for the

iPhone or iPad:

• Creating a navigation-based application

• Creating a UINavigationController object manually in the application delegate

I choose the second method over the first, for various reasons. One is that I feel I get

more control over how the structure of my application is created from the beginning;

another is that the second method makes it easier for me to control the lifetime of the

navigation controller.



2.9 Implementing Navigation Bars | 55



www.it-ebooks.info



Xem Thêm
Tải bản đầy đủ (.pdf) (640 trang)

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×