how to have a NSString value in all classes? - ios

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.

Related

Not understanding shared instance

I am getting confused about how to use shared instance.
This is my set up:
+ (ViewController *)sharedInstance {
static ViewController *_sharedInstance = nil;
if (_sharedInstance == nil) {
_sharedInstance = [[ViewController alloc] init];
}
return _sharedInstance;
}
I also have a property in the ViewController.h file called
#property (nonatomic, retain) CBPeripheral * selectedPeripheral; and under the interface in the ViewController.m file CBPeripheral * _selectedPeripheral; and I make sure to synthesize them
So whenever I do this. It works.
[ViewController sharedInstance].selectedPeripheral = _selectedPeripheral;
NSLog(#"_sharedInstance %#", [[ViewController sharedInstance] selectedPeripheral]);
But if I do this? Without doing the line above. It returns null?
I thought the synthesize would make it so I don't have to assign it again?
NSLog(#"_sharedInstance %#", [[ViewController sharedInstance] selectedPeripheral]);
You are not assigning any value to _selectedPeripheral, thus, is has no value.
Try setting _selectedPeripheral inside your singleton initializer.
I don't know anything about the code, but it implies something needs to be selected. You may have an issue in your selection code as well, but you're class won't magically create objects because it is a singleton ;-)
EDIT
#synthesize only creates the instance variavle (the underscored), so it is available from inside your class. Note this is only necessary, if you overwrite getter and setter as well.
Also note that you posted the getter of the singleton and you have problems with a property. Please poste the code we need to see to help you without guessing.

Access NSMutableArray from another class - Objective C

I have a main ViewController that contains a desginated class. Within that ViewController there is a Container that is linked to an embed ViewController. Within that embed ViewController I am creating an NSMutableArray. I am not trying to access that array inside the main ViewController. I know that if I use:
create_challenge_peopleSelect *myScript = [[create_challenge_peopleSelect alloc] init];
NSLog(#"%#",myScript.selectedCells);
The NSLog will output null because I am creating a new ViewController and that gets rid of the already set array. So my question is how can I access that array without overwriting it?
UPDATE:
Heres where the NSMutableArray is being created:
create_challenge_peopleSelect.h:
#property (strong, nonatomic) NSMutableArray *selectedCells;
create_challenge_peopleSelect.m:
if([selectedCells containsObject:label.text])
{
cell.accessoryType = UITableViewCellAccessoryNone;
[selectedCells removeObjectIdenticalTo:label.text];
}
else
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[selectedCells addObject:label.text];
}
This class is the container class off the main ViewController
No I want to access the selectedCells within my main ViewController, I have been doing things such as:
create_challenge_peopleSelect *myScript = [[create_challenge_peopleSelect alloc] init];
I would prefer to stay away from the App Delegate If possible.
You seem to be unclear on the difference between classes and instances. OK, so, say we have two NSArrays:
NSArray *a = [[NSArray alloc] initWithObjects:#"hello", #"I", #"am", #"an", #"array", nil];
NSArray *b = [[NSArray alloc] initWithObjects:#"so", #"am", #"I", nil];
If I do a.count, I'll get 5 as the answer because the array contains five objects. Meanwhile, if I do b.count, I'll get 3, because that array contains three objects. It isn't that creating b "gets rid of the already set count". They are separate objects completely unrelated to each other.
Your view controller class is the same way. When you create a different instance, it doesn't overwrite the old one -- it's just not the same object. In order to use the original view controller object, you need to get a reference to it.
So how do you get a reference to it? Well, the general answer is you design your app so that the two objects know about each other. There are lots of specific ways to accomplish this. A lot of people will say "Just stick a reference in the app delegate." That is one thing you can do, but it's not always the best choice. It can get out of control if you just stick everything in your app delegate. Sometimes it's the right answer, often other things are the right answer. Another approach is to have an object that knows about both of those objects introduce them to each other. But sometimes there is no such object. So it's situational.
Basically, instead of creating a new view controller, you need to maintain a pointer to the original.
I suggest storing an instance of your UIViewController in the AppDelegate in order to retain the particular instance of the view controller you've created by making it a global variable.
ex. In the App Delegate.h
#import "ViewController.h"
#class ViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (nonatomic) ViewController *viewController;
Then from whatever view controllers' .m's from which you need to read/write to the variable, create a pointer to the application's app delegate, ex:
#import "AppDelegate.h"
#interface WhateverViewController ()
AppDelegate *mainDelegate;
- (void)viewDidLoad {
mainDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
}
So wherever you first create that view controller in your code (before ever using it), initialize it using this global variable. ex. If you're using xibs:
mainDelegate.viewController = [[UIViewController alloc] initWithNibName:#"ViewController" bundle:nil];
[self.navigationController pushViewController:mainDelegate.viewController animated:YES];
ex. If you're using storyboards:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"StoryboardName" bundle:nil];
mainDelegate.viewController = [storyboard instantiateViewControllerWithIdentifier:#"viewControllerID"];
[self.navigationController pushViewController:mainDelegate.viewController animated:YES];
(This is assuming it's in a place other than the app delegate in which case the pointer to the App Delegate isn't needed.)
Then when accessing the array from another UIViewController use
mainDelegate.viewController.array
To access the NSMutableArray from one class to another class use following code.
In the first view controller in which u have declared the object of NSMutableArray, declare the property and synthesize for the same as below,
//In FirstViewcontroller.h class,
#property (nonatomic, strong) NSMutableArray *arrData;
//In FirstViewcontroller.m class
#synthesize arrData;
Also FirstViewcontroller object should be global so you can create the object of FirstViewcontroller in app delegate file.
//appdelegate.h
#property (nonatomic, strong) FirstViewcontroller *objFirst;
//appdelegate.m
#synthesize objFirst;
FirstViewcontroller *objFirst=[[FirstViewcontroller alloc]init];
Now in SecondViewcontroller in which you have to access array,
create the share object of Appdelegate file
//SecondViewcontroller.m
AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
Then use will get the required array as below,
app.objFirst.arrData
This is your required array I hope it will help you.
The basic idea here is that in your original class, the array is referred to by a pointer. Your original class would allocate it and presumably load it. Other parts of your program can be handed the contents of the property, which is a pointer, assign that to their own pointer holder, and use it as if you had declared it there. Please use the above code;
MyClass *aClass = [[MyClass alloc] initWithMyInitStuff];
NSMutableArray *ThatArray = aClass.MyArray;
NSLog("Count of ThatArray: %d", [That.Array count]);
What you've done in the code provided is set a public property for a mutable array...
#property (strong, nonatomic) NSMutableArray *selectedCells;
The NSMutableArray is not "created" by setting that property. At some point in your code you also have to create the NSMutableArray by initialising...
NSMutableArray *selectedCells = [[NSMutableArray alloc] init];
or by using a convenience method such as...
NSMutableArray *selectedCells = [NSMutableArray arrayWithCapacity:(NSUInteger)<initialising capacity>];
or
NSMutableArray *selectedCells = [NSMutableArray arrayWithArray:(NSArray *)<initialising array>];
Initialising an NSMutableArray is often done only once. If it is repeated, the contents are overwritten against the property used to point to the array. As such, a useful location for this is often within the viewDidLoad view controller lifecycle method.

How to make a variable available globally objective c

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;

Synthesized NSMutableArray is returning null

So I've declared this in my appDelegate.h
#property(nonatomic,strong) NSMutableArray *featured;
I've synthesized it like so in my appDelegate.m
#synthesize featured;
When I log that out in the appDelegate with the object stored in there, I get the value it's supposed to have
In a viewController.h file I have declared this
#property(nonatomic,strong) NSMutableArray *featured;
In the viewController.m file I've synthesized it like this
#synthesize featured;
I then print out this line and get a null value
NSLog(#"HERE %#", featured);
That same line prints out the correct value in my appDelegate.m file. I'm completely lost. I've set it up in the way I've done it for a previous class exercise. Thanks in advance!
Edit:
I created the array in appDelegate.m file like so in a method I called loadFeatured
featured = [NSMutableArray array];
for (id dict in tempArray)
{
//NSLog(#"dict=%#",dict);
NSString *shopName = [dict objectForKey:#"shopName"];
NSString *drinkName = [dict objectForKey:#"drinkName"];
NSNumber *likes = [dict objectForKey:#"likes"];
NSNumber *dislikes = [dict objectForKey:#"dislikes"];
NSString *review = [dict objectForKey:#"review"];
Featured *feat = [[Featured alloc] initWithName:shopName drinkName:drinkName likes:likes dislikes:dislikes review:review];
NSLog(#"feat=%#\n\n",feat);
[featured addObject:feat];
}
NSLog(#"there is %d featured",[featured count]);
NSLog(#"HERE %#", featured);
Here is the way, how to access the data stored in the app delegate from your viewcontroller.
You need not synthesize the object in the viewcontroller. Just import your appdelegate file and copy the following code wherever necessary.
NSMutableArray * nArray =[ (AppDelegate*) [[UIApplication sharedApplication] delegate] featured];
The above code gives you the required array from the app delegate.Now you can make use of the nArray object to display the details in the console.
NSLog(#"%#",nArray.description);
It's hard to say how to do this without knowing the structure of your app. You could pass a pointer to the array to your view controller, if you have access to that view controller from the app delegate. The other way is to get a reference to the app delegate in your view controller, and then access its array. That can be done like this:
AppDelegate *appDel = [UIApplication shared application].delegate;
NSArray *myControllerArray = appDel.featured;
You'll need to import your app delegate into your controller's .m file to use this approach.
Since you already declared a property in appDelegate.h you can access it in the other viewController like this:
#import "appDelegate.h"
and you can access the value it by using something like this:
((AppDelegate *)[[UIApplication sharedApplication]delegate]).featured
If you need to access an NSArray or any other object in any class, via AppDelegate, just create a property to access your ViewController, like so, in your AppDelegate class:
#import "ViewController.h"
#property (nonatomic, strong) AppDelegate *appDelegate;
#property (nonatomic, strong) ViewController *viewController;
In your ViewController class:
#import "AppDelegate.h"
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
ViewController *viewControllerREFERENCE = [appDelegate viewController];
Then you'll have access to any value on your ViewController, via AppDelegate.
I hope that helps you.

trying to display information from an object of a NSMutable array that is in AppDelegate from another class with a dot operator

I am trying to figure out how to access and display info from an object from a NSMutable array that is created in my AppDelegate.
From my AppDelegate.h
#property (readonly, retain) NSMutableArray *myRaces;
#end
AppDelegate * appDelegate;
From my AppDelegate.m
extern AppDelegate * appDelegate;
#synthesize myRaces;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
appDelegate = self;
TheRace * orc;
orc = [[TheRace alloc] init];
orc.raceTitle = #"Orc"; [orc modifyStatsFromRace:(NSString*)orc.raceTitle];
NSLog(#" test %d ", orc.massMod);
orc.raceData = #"Orcs are big burly stupid beasts";
myRaces = [[NSMutableArray alloc] init];
[myRaces addObject:orc];
}
I want to call the value of orc.massMod from another class, and cannot figure out how. I tried.
appDelegate.raceSelected = #"Orc";
NSLog(#"Orc");
appDelegate.theMass = appDelegate.myRaces.orc.massMod;
However, "appDelegate.theMass = appDelegate.myRaces.orc.massMod;" failed, the error says
... Property "orc" not found on object type 'NSMutableArray *'
How do I call that info? I want to display the value of massMod, which works in the NSLog from within appDelegate. "appDelegate.theMass" is what holds value for display in my UILabel.
Since you are storing orc in an array, you cannot access it by the name of the variable. You should be able to retrieve it by calling objectAtIndex, e.g.
appDelegate.theMass = ((TheRace*)[appDelegate.myRaces objectAtIndex:0]).massMod;
When you're in another class from Appdelegate and call "appDelegate.myRaces", you got a NSMutableArray. Thus you cannot access the orc object by appending ".orc", because orc is not an attribute of NSMutableArray.
You can write instead
// The cast is not necessary, but is useful for readability
TheRace * myOrc = (TheRace*)[appDelegate.myRaces objectAtIndex:0];
appDelegate.theMass = myOrc.massMod;
but you can easily lost track of which item goes with which index. You can use too an NSMutableDictionary :
-in your AppDelegate.h
#property (readonly, retain) NSMutableDictionary *myRaces;
-in your AppDelegate.m :
myRaces = [[NSMutableDictionary alloc] init];
[myRaces setObject:orc forKey:#"Orc"];
-in your other classes :
TheRace * myOrc = (TheRace*)[appDelegate.myRaces objectForKey#"Orc"];
appDelegate.theMass = myOrc.massMod;
Best way to do define a macro like this:
#define MyAppDelegateObject ((AppDelegate *)[[UIApplication sharedApplication] delegate])
and refer your properties in appdelegate like this:
NSLog(#"Races: %#",MyAppDelegateObject.myRaces);

Resources