Global? Singleton? Isn't that the one who married Prince William? No. That would be Ms Middleton.
Noobies like us tend to get intimidated by these names because they sound so complicated. But the truth is, it is quite simple. When you create an app, often they will have more than 1 ViewControllers - for example a ViewController, where all the main thingy happens. Then there is a Settings button that will bring you to another view, say SecondViewController that changes some of the state of the component in ViewController.
So how do you pass that state back to the ViewController?
GLOBAL VARIABLES
The simple, but crude way is to use Global Variables. Global Variables can get messy because once you use a certain name as global variable, you can not use it again at ANY OTHER PLACES. And this can get confusing when you have many lines of codes and more than one class.
A quick example of Global Variable Declaration is as follows:
In your header (.h) file, input the "allocation" of the variable.
#import <UIKit/UIKit.h>;
extern BOOL MYGlobalVariable;
@interface BattleGameViewController : UIViewController
@end;
"extern" does not declare it. What it does is just "allocate" a memory for that particular variable. Therefore to declare it, one need to declare in the implementation file (*.m) as follows:
#import "MyAppHeader.h"
@implementation BattleGameViewController
BOOL MYGlobalVariable = NO;
So to use this variable in another class, all you need to do is import "MyAppHeader.h" and MYGlobalVariable should be ready to be used.
It works well, in fact, I also used it in some of my early apps. That is until I learn about Singleton.
SINGLETON
Believe it or not, MOST of us NOOBIES already used Singleton. The most common Singleton we use is.... *drumroll*... NSUserDefaults!
Do you like NSUserDefaults? I do. It is so easy and simple. And that is why you also should use Singleton in variable aspects of your app. It will make your coding very nice and easy to maintain.
How to implement a Singleton? I am no ObjC Guru, that much I can tell you, but hey, why reinvent the wheel, when some gurus have created the Singleton class for you? There are loadsssss of ways to write a Singleton Class, and you can find them here:
StackOverflow: Samples of Singletons
Anyway, here is MY singleton class. I used this Singleton class in one of my latest app - Clock Stand for iPad. I stripped off all the other variables and leave just 1 for example so that it is clear for you to see how to implement it.
//
// MySingletonCenter.h
// ClockForiPad
//
// Created by Emir Fithri Samsuddin on 6/20/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface MySingletonCenter : NSObject {
// Your variables go here
// here's one example:
BOOL is24Hour;
}
// Your property settings for your variables go here
// here's one example:
@property (nonatomic, assign) BOOL is24Hour;
// This is the method to access this Singleton class
+ (MySingletonCenter *)sharedSingleton;
@end
And the implementation file (*.m)
//
// MySingletonCenter.m
// ClockForiPad
//
// Created by Emir Fithri Samsuddin on 6/20/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import "MySingletonCenter.h"
@implementation MySingletonCenter
static MySingletonCenter *shared = NULL;
@synthesize is24Hour;
- (id)init
{
if ( self = [super init] )
{
// init values
// here you assign initial values to your variable.
// in my case, I save all these values into NSUserDefaults as users preference.
// so i do the necessary things to ensure that happens.
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
if ([def objectForKey:@"is24Hour"]==nil) {
is24Hour = NO;
[def setBool:self.is24Hour forKey:@"is24Hour"];
[def synchronize];
} else {
// read from NSUserDefaults
self.is24Hour = [def boolForKey:@"is24Hour"];
}
}
return self;
}
+ (MySingletonCenter *)sharedSingleton
{
@synchronized(shared)
{
if ( !shared || shared == NULL )
{
// allocate the shared instance, because it hasn't been done yet
shared = [[MySingletonCenter alloc] init];
}
return shared;
}
}
- (void)dealloc
{
NSLog(@"Deallocating singleton...");
[super dealloc];
}
@end
Now, to create the Singleton Class, all you need to do is Right Click on the left panel of XCode and Choose Add File... and Choose Objective-C Class. Give a proper name (for eg, MySingletonCenter.h and MySingletonCenter.m) to it, select NSObject as its class and add to project. After that just copy and paste the above Singleton code into the corresponding .h and .m. And you're set to go.
To use Singleton in another class is easy.. in fact super easy just like NSUserDefaults.
1. #import "MySingletonCenter.h"
2. Everytime you want to read or write to it:
MySingletonCenter *tmp = [MySingletonCenter sharedSingleton];
// write
tmp.is24Hour = YES;
// read
BOOL new = tmp.is24Hour;
SUPER EASY! WHAT UP!
Hi Dro,
ReplyDeleteThanks for your comment.
A new tutorial is coming soon. :)
I can't get your tutorial to work. I guess it is best to never underestimate the confusion of a noobie. I have a multi-view app that worked very well before I started this tutorial, and I did my best to triple-check all the steps you described. I'm pretty sure I made no mistakes in the MySingletonCenter .h and .m files. All I changed was my variable names - (both are BOOLs).
ReplyDeleteBut there was a little ambiguity over where to add the statement
#import "MySingleton.h"
which I think should actually be
#import "MySingletonCenter.h"
I added it to my views .h files.
And also I had to guess where to insert the read and write code - I tried putting it into IBAction routines in my views .m files. I got a fatal error on every line that referred to the variables I thought were created in MySingletonCenter.h and MySingletonCenter.m saying "Use of undeclared identifier 'variableName'". I'll try initializing these variables the usual way in each view, but now I may end up with multiple variable definition errors. So I hope you'll create a sample project with multiple views and post it. Thanks.
Very clear explanation, and the tutorial worked great. Thanks!
ReplyDeleteThanks all for your nice words! :D
ReplyDeleteRicardocanada, you are correct on the #import "MySingletonCenter.h".
Anyway, not sure you are still interested or not, but I have made a downloadable sample project and it is available for download in the blog post.
Thank you all!
how would you refresh the data if it's changed in the NSUserData file?
ReplyDeleteYour sir are now my personal jesus christ! Cheers! :)
ReplyDeleteNoobies like us tend to get intimidated by these names because they sound so complicated. But the truth is, it is quite simple. Now its time to avail power only dispatch servicesfor more details.
ReplyDelete