A "token" will be given upon authentication in a form of xml file with some other elements.
I managed to extract the token, and display it in the calling class, let's say parser.m.
However, I need to make the content of that variable available globally, so that I can reuse the same token. How do I do that?
Please note that a different token will be given upon the next authentication.
.h:
#interface Parser : NSObject <NSXMLParserDelegate>{
NSXMLParser *parser;
NSMutableString *element;
NSMutableString *token;}
#property (nonatomic, retain) NSMutableString *token;
#end
.m:
#import "Parser.h"
NSLog(#"tOKEn called from main: %#", parser->token);
It is not able to access the "token" that was declared under parser.m
How do I go around this?
Update 1:
I found out that using #public serves the purpose too. Not sure whether its a good move or not since I will be needing the token in all my API calls.
create a singleton class for global variable in objective c
in .h file
#import <Foundation/Foundation.h>
#interface Singleton : NSObject
{
///......
}
+ (Singleton *)sharedSingleton;
in .m file
#import "Singleton.h"
#implementation Singleton
static Singleton *singletonObj = NULL;
+ (Singleton *)sharedSingleton
{
#synchronized(self)
{
if (singletonObj == NULL)
singletonObj = [[self alloc] init];
}
return(singletonObj);
}
and use this in another file
#import "Singleton.h"
//.....
Singleton *sinObj = [Singleton sharedSingleton];
and create variables inside that and also write setter and getter method for that variable in singleton class. Access this method and variable using sinObj object of singleton class
IMO singletons are a overused curse.
Your (every) application should have a layers structure, and this token variable shouldn't leave communication layer. If it does this means that something is wrong with your application design. Note that token is needed only to do posts and every other part of code doesn't need it.
For temporary variables, consider using a singleton instance, such as the MySingleton class illustrated in this answer. How to create a singleton: What should my Objective-C singleton look like?.
You can access the variable like this: [MySingleton sharedSingleton].variable; Singleton is a good choice if you have a lot of global variables, but if only one better to use NSUserDefaults.
NSUserDefaults are for things that require persistance, i.e. you are planning on storing them between app starts. Good starter: http://mobile.tutsplus.com/tutorials/iphone/nsuserdefaults_iphone-sdk/
Also please read: Are global variables bad?
Try this:
[[NSUserDefaults standardUserDefaults]setObject:_YourObject_ forKey:#"token"];
NSString *str = [[NSUserDefaults standardUserDefaults] stringForKey:#"token"];
Or You can use singleton.
Try to Declare that varible into Appdelegate as a property and syntesize it in .m .
Or aceess that varible in any class using this.
AppDelegate * appdelegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
AppDelegate.yourvarible;
or either you used NSUserDefault.
[[NSUserDefaults standardUserDefaults]setObject:token forKey:#"tokan"];
You can create a property in ur appdelegate and set the property when u get the token.
//getter
NSString *token=[(MyAppDelegate *)[[UIApplication sharedApplication] delegate].recievedToken;
//setter
[(MyAppDelegate *)[[UIApplication sharedApplication] delegate].recievedToken=token;
Related
I need to capture data in the viewController and stay stored during the execution of the app and you can use it in any other View that I have, try creating a NSString in AppDelegate as follows:
AppDelegate.h
property (Retain, nonatomic) NSString * token;
AppDelegate.m
synthesize token;
and then call it in the other class as follows
adding include
#include "AppDelegate"
creating an object
AppDelegate * theToken = [[AppDelegate allow] init];
label.text = theToken.token;
but not working me, in some ViewController appears nill
The problem is that you're creating a brand new instance of the AppDelegate instead of accessing the current one.
Instead of:
AppDelegate * theToken = [[AppDelegate alloc] init];
try this:
AppDelegate * theToken = (AppDelegate*)[[UIApplication sharedApplication] delegate];
Edit: As rmaddy and Louis Tur also pointed out in the comments, your use of retain and synthesize are pre-ARC relics.
"Strong" is the ARC equivalent of "retain" so you can update your property to the following in order to maintain a strong reference:
property (strong, nonatomic) NSString * token;
Furthermore, once upon a time (until some time post-ARC but pre-iOS6 if I remember correctly), synthesizing your .h properties in your .m was required. But in the modern era, it's generally good practice to leave out synthesize in your .m and instead access the property within AppDelegate.m using "self"; for example, self.token.
I'm having issues with dictionary, i want a dictionary create only once to save data to plist file. So how to create singleton dictionary ? Thank in advance
You can create one instance of NSDictionary in AppDelegate, make this dictionary as a public property of class.
#property (nonatomic, strong) NSMutableDictionary *myDict;
Initialize this in - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions method.
Now access it through out the app -
((AppDelegate *) [UIApplication sharedApplication].delegate).myDict
Only one instance will be created for your use.
As you responded in comments, you need a global variable. Bellow is the receipt.
Here is what you can do:
Add variable extern definition at the top of your AppDelegate.h file:
extern NSMutableDictionary *MyGlobalDictionary;
Add variable definition at the top of your AppDelegate.m file:
NSMutableDictionary *MyGlobalDictionary;
Now you need to initialize the dictionary, can be done in initialize method of you AppDelegate. In AppDelegate.m add this somewhere in #implemetaion of AppDelegate:
+ (void)initialize {
MyGlobalDictionary = [[NSMutableDictionary alloc] init];
}
How to use:
Whenever you need it, just #import your AppDelegate.h file. Bellow is an example how to use:
NSLog(#"%#", [MyGlobalDictionary objectForKey:#"someKey"]);
Important:
While creating singleton is extremely easy it is considered to be a bad practice. Think about passing your dictionary to objects that can be interested in it. Or may be define some global class singleton if it is unavoidable.
I have implemented Opencv in one of my project. In an opencv .mm file, I need to access the appdelegate object for global access of an array but it is giving Linker Error all the time (When I am trying to import the AppDelegate Class). So I have created an NSObject Class, still I can not access the Global Array which is created as the #property of the NSObject (I have imported the NSObject class in the .mm file). Array is giving the NULL value.
So where do I create the Array by which I can access the array in my whole project?
I can not use the NSUSerDefaults and DocumentDirectory. Because I want to save a lots of images and video links in that array, So I can not use NSUserDefaults and I don't want to use again the phone memory for the temp file as because I am picking the images from the Photolibrary, so DocumentDirectory is discarded, So Is there any way by which I can create the global array and access them from the openCV files i.e objective CPP files?
you can make class as UserdataSingleton which overrides NSObject. which you can use all over your application to share data globally (for your case array). this code template may help you:
#import <Foundation/Foundation.h>
#interface UserDataSingleton : NSObject
{
#private
NSArray *globalArray;
}
+(UserDataSingleton *) getInstance;
-(void)saveInUserDatasingletonWithArray:(NSArray *)array;
-(NSDictionary *)getGlobalArray;
#end
and implementation file will be some thing like:
#import "UserDataSingleton.h"
#implementation UserDataSingleton
static UserDataSingleton *userDataSingletonInstance;
+(UserDataSingleton *) getInstance
{
if (userDataSingletonInstance == nil) {
userDataSingletonInstance = [[UserDataSingleton alloc] init];
}
return userDataSingletonInstance;
}
-(void)saveInUserDatasingletonWithArray:(NSArray *)array
{
globalArray = array;
}
-(NSDictionary *)getGlobalDictionary
{
return globalArray;
}
#end
================== usage:
#import "UserDataSingleton.h"
#define USERDATASINGLETON (UserDataSingleton *)[UserDataSingleton getInstance]
......................your code...
NSArray *this_IS_Array_Populated_here_For_Global_Access = [NSArray alloc] initWith....];
[USERDATASINGLETON saveInUserDatasingletonWithArray:this_IS_Array_Populated_here_For_Global_Access];//you put your array for global access.
later some where in any other view or view controller you can get that global array for example lets say you have YourViewController class:
NSMutableArray *yourArrayFromWebResponse = [USERDATASINGLETON getGlobalArray];
thanks
Note that Objective C is a superset of C. Thus, you can have regular C variables in your program. My favorite is to make a global variable for my appDelegate. Put this in your app delegate's .h file:
MyAppDelegateClass * appDelegate;
(change "MyAppDelegateClass" to your appDelegate's class name) and put this in application: didFinishLaunchingWithOption: method in your app delegate's .m file:
appDelegate = self; // set universal global variable
Now just #import your app delegate's .h file and have access to your appDelegate from anywhere.
You may try to create a singleton objet like and access it from everywhere
you could define a macro in your delegate like so:
#define sharedAppDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)
and then in the class which you want to access your array import your AppDelegate class, boiler plate would be:
#import AppDelegate.h
and then just use:
NSArray *arrayYouWanted = [AppDelegate sharedAppDelegate].yourPropertyArrayName;
You can also store it in NSUserDefaults if you want to persist it.
I remember having struggled at a particular time of my learning phase with implementing the concept of 'global' variables in iOS that can be accessed on any class throughout the app. I read through many excellent tutorials like this one by Matt Galloway.
I just went through the code I had finally implemented and I realize I had done it in a very different way than any of these tutorials. I wanted to know the possible disadvantages/advantages of the method I adopted
My h file was something like :
#interface GlobalVariables : NSObject
+(void)setUsername:(NSString *)string;
+(NSString *)getUsername;
#end
and my m file was :
static NSString *name;
#implementation GlobalVariables
+(void)setUsername:(NSString *)string{
name = string;
}
+(NSString *)getUsername{
return name;
}
#end
I'd set the global variable in any other class like
[GlobalVariables setUsername:#"user1"];
and get it in other classes as
self.nameLabel.text = [GlobalVariables getUsername];
Is there anything wrong/right about what I did? Any comment towards the right direction would be much appreciated. Thank you :)
What you are doing is smelly but how you are doing it is fine (almost - see below)...
basically there are unavoidable situations where you need to store global state...
you should try as hard as you can to avoid them... here are my ramblings:
If the state you are keeping is truly global and infrequently accessed, then store them in the user defaults using NSUserDefaults:
[[NSUserDefaults standardUserDefaults] setObject:#"123456789" forKey:#"apiKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
if your state isn't truly 'global' then you should try to find the correct context, even if it is an artificial one:
#interface EncryptionContext: NSObject
#property int someProperty
#end
What you are doing is fine, and I prefer it to a singleton... basically anything you can do with a singleton you can do with a +[Class classMethod] or even a nakedCFunction()
in a multithreaded app be sure to #synchronize your accessors and setters so that they are always in a consistent state.
In reference counted code you will want to retain the new objects and release the old ones...
static NSString *name;
#implementation GlobalVariables
+(void)setUsername:(NSString *)string{
id tmp = name;
name = [string copy];
[tmp release];
}
+(NSString *)getUsername{
return name;
//or for more atomic operation [[name copy] autorelease]
}
#end
I used to declare variale in appdelegate and make it as sharable in all the classes (If the variable is global ) .
appDelegate = (StoryAppDelegate*)[[UIApplication sharedApplication]delegate];
this was the code am using normally to access appdelegate variable. Now am trying a story board application and its not working for me . while declaring appdelegate it shows an error "Unknown type name StoryAppDelegate".
StoryAppDelegate*ss;
this is the code am using .
Any help appreciated .
Just don't use the app delegate. That isn't what it's for.
Instead, create a specific class to own the responsibility + knowledge, make it a singleton and have all classes that require it get it via it's 'sharedController' (or whatever you call it) class method.
Or use a 'constants' file with a static variable or something (just not the app delegate).
Storyboard is used only for design, not changes to the code.
For that, you'd use:
AppDelegate *app;
in the header file of the view's controller.
And in the implementation file,
app=(AppDelegate *)[[UIApplication sharedApplication]delegate];
Then you can just use app.yourVariable
I would recommend using a singleton instance of your global variable as they have bailed me out of your exact situation multiple times. Here is an example I'm currently using to implement a singleton. This methodology is also ARC-safe as well
mySingleton.h
#import <Foundation/Foundation.h>
#interface mySingleton : NSObject {
}
+ (NSMutableDictionary *) myMutableDict;
#end
mySingleton.m
#import "mySingleton.h"
#implementation mySingleton
+ (NSMutableDictionary *)myMutableDict
{
static NSMutableDictionary *singletonInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singletonInstance = [[NSMutableDictionary alloc]init];
});
return singletonInstance;
}
#end
As long as you include mySingleton.h in all of your view controllers you can access the data via [mySingleton myMutableDict]. For example: [[mySingleton myMutableDict] setObject:myObject forKey:myKey]; This will of course work with any object type.
It seems the case of circular dependency.
use #class StoryAppDelegate;
instead of
#import "StoryAppDelegate.h"
in your header file.