In iPhone development, if/when you need a single instance of a variable that can be shared and manipulated where and how should you implement this. Thus far I have found 2 ways of doing so. The first would be to add the global variables to your AppDelegate (which can be done and will be explained but isn’t the preferred method). The second and ‘correct’ way of going about globals is to create a Singleton.
For the following examples we will assume the global variable you are trying to implement is a User object.
User.h
#import <Foundation/Foundation.h>
@interface User : NSObject {
NSString *username;
NSString *password;
NSString *accountType;
}
@property (nonatomic, retain) NSString *username;
@property (nonatomic, retain) NSString *password;
@property (nonatomic, retain) NSString *accountType;
User.m
#import “User.h”
@implementation User
@synthesize username;
@synthesize password;
@synthesize accountType;
App Delegate Method
ApplicationAppDelegate.h
#import “User.h”
@interface ApplicationAppDelegate : NSObject <UIApplicationDelegate> {
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
UIWindow *window;
User *user;
}
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) User *user;
ApplicationAppDelegate.m
#import “ApplicationAppDelegate.h”
@implementation ApplicationAppDelegate
@synthesize window;
@synthesize user;
#pragma mark -
#pragma mark Application lifecycle
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:tabBarController.view];
// Override point for customization after app launch
[window makeKeyAndVisible];
user = [[User alloc] init];
}
Then from any view controller you can access the Delegate variable as such.
SomeViewController.m
UIApplication *app = [UIApplication sharedApplication];
app.user.username = @”Username”;
While this can be done and will work. The overall use of the AppDelegate for this functionality is incorrect. The AppDelegate should be used for the following 2 reasons:
- implemenations of the
NSApplication
delegate methods (includingapplicationDidFinishLaunching:
to finalize application construction)
- handling menu items for items that don’t exist in a window (for example, opening the application Preferences window)
So, on that note, lets implement a Singleton. The ‘correct’ way of creating a single global instance of an object that can be accessed and manipulated by the view controllers.
Singleton Method
First we need to make some changes to our User class as such:
User.h
#import <Foundation/Foundation.h>
@interface User : NSObject {
NSString *username;
NSString *password;
NSString *accountType;
}
@property (nonatomic, retain) NSString *username;
@property (nonatomic, retain) NSString *password;
@property (nonatomic, retain) NSString *accountType;
+ (User *)sharedUser;
@end
User.m
#import “User.h”
static User *sharedUser = nil;
@implementation User
@synthesize username;
@synthesize password;
@synthesize accountType;
#pragma mark -
#pragma mark Singleton Methods
+ (User *)sharedUser {
if(sharedUser == nil){
sharedUser = [[super allocWithZone:NULL] init];
}
return sharedUser;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedManager] retain];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (unsigned)retainCount {
return NSUIntegerMax;
}
- (void)release {
//do nothing
}
- (id)autorelease {
return self;
}
@end
Now, in any view controller we need to access/manipulate the ‘global’ user we can do:
SomeViewController.m
#import “SomeViewController.h”
#import “User.h”
@implementation SomeViewController
- (void)someFunction{
User *user = [User sharedUser];
user.username = @”Username”;
}
@end