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.
Related
I have viewController with a global property 'notesArray", and I want to get it from AppDelegate through singleton.
Here is my appViewController.h
#import <UIKit/UIKit.h>
#interface AppViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
NSMutableArray *notesArray;
}
#property (nonatomic, strong) NSMutableArray *notesArray;
+ (AppViewController*)sharedManager;
#end
Here is my AppViewController.m
#implementation AppViewController
#synthesize notesArray;
+ (AppViewController*)sharedManager {
static AppViewController *sharedManager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[self alloc] init];
});
return sharedManager;
}
...
#end
My app works fine, but I need to save it's state in NSUserDefaults, so in AppDelegate/applicationDidEnterBackground: I make
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[NSUserDefaults standardUserDefaults] setObject:[AppViewController sharedManager].notesArray forKey:#"savedNotes"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
But the problem is that [AppViewController sharedManager].notesArray = nil.
I tried to set breakpoint to applicationDidEnterBackground: and all data from [AppViewController sharedManager] = nil.
Few observations:
notesArray is not a global property. It is a property on instances of AppViewController. Now in #2 we see that you intend it to be a singleton, but since ObjC doesn't really have a good way to prevent someone else from creating a second object of this type, are you sure you're not creating a second copy e.g. by creating an object of that type in a XIB? This is probably not your problem (see #3), but I just wanted to cover all the bases.
Your sharedManager method implies that you're seeing AppViewController as a singleton. That's an unusual thing to do with a view controller. Usually you would have several view controllers, and the singleton would be part of the model they share. Even better, you'd just give each view controller a pointer to the model object that has this array, and if you ever need a second list, everything will just work. Also, why is it called "manager"? It's a view controller.
Have you stepped through your code in the debugger to see what is going on? What value does notesArray have while you're trying to use it in applicationDidEnterBackground:? I do not see anywhere in your code that you initialize notesArray. So you just have an empty pointer to an object (i.e. notesArray is likely nil). You probably meant to add an init method to your singleton's class that creates an NSMutableArray instance and remembers its address in notesArray?
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.
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;
I was wondering how can I share a NSDictionary objects among several view controllers which basically are tabs in my application.
I tried using a protocol, like in Java, so that I can cast to the protocol and access the property. That doesn't seem to work.
Also I had a look at similar question at
How to share data globally among multiple view controllers
But I observed that the appDelegate method is not safe and may lead to memory leak.
Similarly injection on class A into class B will create the same problem.
So can anyone suggest me any method which i should study or implement in my code?
If you wants to share only Dictionary, why don't you go for class method using from helper class.
+(NSDictionary *)shareMethod
{
return dict;
}
You can use singleton class for sharing the data
Check this Singleton class
MyManger.h
#import <foundation/Foundation.h>
#interface MyManager : NSObject {
NSMutableDictionary *_dict
}
#property (nonatomic, retain) NSMutableDictionary *dict;
+ (id)sharedManager;
#end
MyManger.m
#import "MyManager.h"
static MyManager *sharedMyManager = nil;
#implementation MyManager
#synthesize dict = _dict;
#pragma mark Singleton Methods
+ (id)sharedManager {
#synchronized(self) {
if(sharedMyManager == nil)
sharedMyManager = [[super allocWithZone:NULL] init];
}
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
dict = [[NSMutableDictionary alloc] init];
}
return self;
}
You can access your dictionary from everywhere like this
[MyManager sharedManager].dict
I found a way out. Since I want a dictionary to be shared across, I declared a method in my protocol
- (void) setSingleHouse:(NSDictionary*) singleHouse;
In each of my controller I implemented the method in a appropriate manner. Hence I was able to share across them for now.
Also I figured out that I was casting in a wrong way earlier i.e (#protocol(protocol name)). Now changed it into NSObject .
Sorry for the fuss.
I advise you not to use a property in your appDelegate instance. This pattern doesn't improve code reusability.
Basicly your shared NSDictionnary is your model. So, if you want your code to follow the MVC design parttern, you should create a class with a shared instance that would contain your NDDictionnary in a public property.
This is well explained in this post
This way, you will access your shared NSDictionnary this way
:
NSDictionary* sharedDictionnary = [MyModel sharedInstance].sharedDictionary;