Reputation: 35
I'm developing an app for iPad that often needs to share variables. Too me it seems like the easiest solution would be to create a class with global variables instead of focusing on passing back and forth - as I've also had some problems with that.
What's the easiest way to create and use global variables in objective-C for iPad IOS7 using Xcode 5 with storyboards?
(I know there are duplicates but I can't make it work)
Upvotes: 0
Views: 246
Reputation: 8267
Edit: following @nhgrif and others comments, I am slightly changing my answer
The way to pass variables or use global variables really depends on what you try to do.
Here are few ways:
Passing a value from one view to the other can simply be done before adding it to the stack as so:
ViewController *viewController = [[ViewController alloc] init];
viewController.yourIntegerValue = 42;
[self presentViewController:viewController animated:YES completion:nil];
NSUserDefaults are great for generic small chunks of data which you like to pass around or save for later use. see example from AlwaysWannaLearn, I usually build and store NSDictionary for all the generic value (with keys). (also see comment from @nhgrif which I agree with)
AppDelegate solution is another way to go as @Martin Koles suggested. Perhaps ok for a single set of value, I would avoid it if just for the sake of having all my globals in one place.
Singleton solution (original answer). it is simple, expandable, elegant and efficient. I usually add one of them to any project I create.
here is how to do it quickly:
create a new file : MyManager.h
#import <foundation/Foundation.h>
@interface MyManager : NSObject {
NSString *someProperty;
}
@property (nonatomic, retain) NSString *someProperty;
+ (id)sharedManager;
@end
create a new file : MyManager.m
#import "MyManager.h"
@implementation MyManager
@synthesize someProperty;
#pragma mark Singleton Methods
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
}
return self;
}
- (void)dealloc {
// Should never be called, but just here for clarity really.
}
@end
Thats it really - this class will hold your global functions and values
To use this nifty trick , paste the following line anywhere else in your project
MyManager *sharedManager = [MyManager sharedManager];
//int getValuefromSingleton = sharedManager.MyFunctionOrValue;
Upvotes: 1
Reputation: 5247
The easiest way to have a global wide variable that does not preserve state is to have a property on an AppDelegate (which is a Singleton in your app):
In AppDelegate.h file:
@property (strong, nonatomic) NSString *globalString;
And everywhere you need access:
#import "AppDelegate.h"
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
// use appDelegate.globalString ...
and if you need to use AppDelegate more then once in your class, then define it as property and lazily initiate:
@property (nonatomic, strong) AppDelegate *appDelegate;
- (AppDelegate *)appDelegate
{
if (!_appDelegate) {
_appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
return _appDelegate;
}
However, you should always try to avoid that as it goes against OOP rules. I suggest you read iOS Design Patterns especially MVC, Facade and Singleton: iOS Design Patterns
Singleton NSUserDefaults
can be used as well, but this is rather for preserving state as it survives app termination.
Upvotes: 0
Reputation: 114975
I try to only use NSUserDefaults
for relatively simple values that need to persist between executions of an app - for more complex data Core Data is probably more appropriate.
For transient data, I prefer to use a data model class.
The data model class will have the required properties and sometimes some class or instance methods to manipulate the data. Once you have your data in a model class it is normally pretty simple to pass the reference between your view controllers and avoid the need for 'globals'. If you really do need 'globals' then you can use a singleton pattern - for example, [UIApplication sharedApplication] is a singleton.
You can create a singleton using the following structure
MyData.h
@interface MyData : NSObject {
NSString *someProperty;
}
@property (nonatomic, retain) NSString *someProperty;
+ (id)sharedMyData
@end
MyData.m
#import "MyData.h"
@implementation MyData
#pragma mark Singleton Methods
+ (id)sharedMyData {
static MyData *sharedMyData = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyData = [[self alloc] init];
});
return sharedMyData;
}
- (id)init {
if (self = [super init]) {
someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
}
return self;
}
Then, wherever you need to access your data you can get a reference to it using [MyData sharedMyData];
Upvotes: 0
Reputation: 9852
Easiest and Simplest way of implementing and using Singleton Pattern:
Create a NSObject inherited class, your header file (.h) should be like this:
@interface MySingletonClass : NSObject
//this method will be used to get singleton instance
+ (MySingletonClass *)sharedInstance;
//some variables getters and setters
- (void)setName:(NSString *)name;
- (NSString *)name;
- (void)setAge:(int)age;
- (int)age;
@end
This would be your implementation (.m) class:
@interface MySingletonClass() {
}
//your global variables
@property (nonatomic, strong) NSString *name;
@property (nonatomic) int age;
@end
@implementation MySingletonClass
static MySingletonClass *sharedInstance = nil;
//this method will be used to get singleton instance
+ (MySingletonClass *)sharedInstance {
if(sharedInstance == nil){
sharedInstance = [[MySingletonClass alloc] init];
}
return sharedInstance;
}
-(id)init {
if(self = [super init]) {
_name = @"";
_age = 0;
}
return self;
}
//some variables getters and setters
- (void)setName:(NSString *)name {
_name = name;
}
- (NSString *)name {
return name;
}
- (void)setAge:(int)age {
_age = age;
}
- (int)age {
return age;
}
@end
you can also define your variables in header file too.
You can use set/get your variables throughout the application like this:
[[MySingletonClass sharedInstance] setName:@"Test"];
NSString *name = [[MySingletonClass sharedInstance] name];
Upvotes: 1
Reputation: 3204
Rather using global variables, you should use NSUserDefaults
or Keychain
which store key-value pairs and you can use them anywhere and in any controller of your application. Global variables are generally not preferred due to less security. Their value can be changed easily. Keychain
and NSUserDefaults
are more secure compared to global variables and you can store multiple values in a single place. A sample for using NSUserDefaults
is as follows where value is stored in it and used anywhere in the application.
For Storing key-value pair :
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:[finalDetails valueForKey:@"Std_Id"] forKey:@"Std_Id"];
For fetching that value in some other controller.
NSString *stdId = [[NSUserDefaults standardUserDefaults] valueForKey:@"Std_Id"];
Upvotes: 0