As the title says I need to use same variable in different viewcontllers.
Until this day when I want to use a variable in different viewcontllers I send that specific variable via segues but I don't think that is a good way it requires program to carry variables from one point to another and if there are 5 view controllers this can be messy.
When I search the internet I always found codes about sending variables from one to another by segues and I have read something about global variables but I am not sure that is the one.
Example:(3 view controller program)
User opens the app and at the first viewcontller clicks ''3'' button ( or 1-2-3-4-5) the int x variable become x=3.Later he choses to go on.
Second view controller writes on screen x+x user clicks to 3 viewcontroller.(code is written inside)
Third view controller writes on screen x*x user clicks to 3 view controller.(code is written inside)
As you can see I have used that x variable in different view controllers and please remember I don't want to transfer variables between them so any ideas for that and is this kind of a thing possible.
My Guess using pointers or taking some space in memory my malloc and pointing it from anotherviewcontroller might work.
Answer:As stated in answer below there are two ways this one is suitable for me.
1 view controller
int x =5;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSNumber numberWithInt:x] forKey:#"keyForTheValue"];
[defaults synchronize];
2 view controller
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
int y = [[defaults objectForKey:#"keyForTheValue"] intValue];
intyazi.text = [[NSString alloc] initWithFormat:#"%d", y];
There are several ways to avoid passing the variable from ViewController to ViewController.
But keep in mind, that in some cases it's better to pass it.
Singleton Datacontainer
One way would be using a Singleton Datacontainer:
Header (Threadsafe implementation):
#import <foundation/Foundation.h>
#interface MyManager : NSObject {
NSInteger *someProperty;
}
#property (nonatomic, retain) NSInteger *someProperty;
+ (id)sharedManager;
#end
Implementation:
#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]) {
// Default value
someProperty = #0;
}
return self;
}
#end
NSUserDefaults
Or you could use NSUserDefaults. Which does store the value persistent in the user directory and is also available on the next startup.
Storing a value:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSNumber numberWithInt:yourIntValue] forKey:#"keyForTheValue"];
[defaults synchronize];
Loading the value:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
int yourIntValue = [[defaults objectForKey:#"keyForTheValue"] intValue];
Related
In my project I have a settings class with properties with custom setters that access NSUserDefaults to make everything simpler. The idea is that Settings class has
#property NSString *name
which has custom getter that gets the name value from NSUserDefaults and a setter that saves the new value there. In this way throughout the whole project I interact with the Settings class only to manage user defined preferences. The thing is that it seems way too repetitive to write all the getters and setters (I have about 50 properties), and would like to create one setter and one getter that would work for all variables. My only issue is how to get hold of the name of the variable within the setter.
The final question then is: is it possible to find out within a getter or setter for which property is the function being called?
If you have some other approach I would appreciate it too but considering that I would like to keep all the NSUserDefaults stuff in one class, I can't think of an alternative that doesnt include writing 50 getters and setters.
Thanks!
Another approach could be this.
No properties, just key value subscript.
#interface DBObject : NSObject<NSCoding>
+ (instancetype)sharedObject;
#end
#interface NSObject(SubScription)
- (id)objectForKeyedSubscript:(id)key;
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;
#end
On the implementation file:
+ (instancetype)sharedObject {
static DBObject *sharedObject = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedObject = [[DBObject alloc] init];
});
return sharedObject;
}
- (id)objectForKeyedSubscript:(id)key {
return [[NSUserDefaults standardUserDefaults] objectForKey:key];
}
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key {
[[NSUserDefaults standardUserDefaults] setObject:obj forKeyedSubscript:key];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Now, you can use it like this:
// You saved it in NSUserDefaults
[DBObject sharedObject][#"name"] = #"John";
// You retrieve it from NSUserDefaults
NSLog(#"Name is: %#", [DBObject sharedObject][#"name"]);
I this this is the best approach and is what i will use in the future.
The setter and getter in this case is simple, you can do like this:
- (void)setName:(NSString *)name {
[[NSUserDefaults standardUserDefaults] setObject:name forKey:#"name"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (NSString *)name {
return [[NSUserDefaults standardUserDefaults] objectForKey:#"name"];
}
If you want to use a simple approach for all properties:
- (id)objectForKey:(NSString *)key {
return [[NSUserDefaults standardUserDefaults] objectForKey:key];
}
- (void)setObject:(id)object forKey:(NSString *)key {
[[NSUserDefaults standardUserDefaults] setObject:object forKey:key];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Instead of creating many properties, create many keys, each key is something you want to save or retrieve.
Example of keys:
static NSString *const kName = #"name";
static NSString *const kLastName = #"lastName";
I found your question very interesting and I said to myself "Challenge accepted!".
I've created this project on Github.
Basically, all you have to do is subclass the VBSettings class and then declare de properties, like this:
#interface MySettings : VBSettings
#property (strong, nonatomic) NSString *hello;
#end
The value of "hello" will be saved to NSUserDefaults with the key "hello". Example of usage:
MySettings settings = [[MySettings alloc] init];
settings.hello = "World!"; //The value is saved in NSUserDefaults
NSLog(#"%#", settings.hello); //The value is restored from NSUserDefaults.
One possibility would be to use KVO to detect when your properties change.
E.g.:
#interface Settings : NSObject
#property NSString *one;
#property NSString *two;
#end
#implementation Settings
- (instancetype)init
{
self = [super init];
if (self) {
[self addObserver:self forKeyPath:#"one" options:NSKeyValueObservingOptionNew context:NULL];
[self addObserver:self forKeyPath:#"two" options:NSKeyValueObservingOptionNew context:NULL];
}
return self;
}
- (void)dealloc
{
[self removeObserver:self forKeyPath:#"one"];
[self removeObserver:self forKeyPath:#"two"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(#"Key: %#, Change: %#", keyPath, change);
}
#end
In a different class, use the standard property access:
Settings *settings = [[Settings alloc] init];
settings.one = #"something for one";
The Settings object logs:
Key: one, Change: {
kind = 1;
new = "something for one"; }
You could try to use dynamic Getter and Setter declarations as noted in this answer.
First create generic functions that you want all the properties to use:
- (id)_getter_
{
return [[NSUserDefaults standardUserDefaults] objectForKey:NSStringFromSelector(_cmd)];
}
- (void)_setter_:(id)value
{
//This one's _cmd name has "set" in it and an upper case first character
//This could take a little work to parse out the parameter name
[[NSUserDefaults standardUserDefaults] setObject:object forKey:YourParsedOutKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Then create the dynamic method generator:
+(void)synthesizeForwarder:(NSString*)getterName
{
NSString*setterName=[NSString stringWithFormat:#"set%#%#:",
[[getterName substringToIndex:1] uppercaseString],[getterName substringFromIndex:1]];
Method getter=class_getInstanceMethod(self, #selector(_getter_));
class_addMethod(self, NSSelectorFromString(getterName),
method_getImplementation(getter), method_getTypeEncoding(getter));
Method setter=class_getInstanceMethod(self, #selector(_setter_:));
class_addMethod(self, NSSelectorFromString(setterName),
method_getImplementation(setter), method_getTypeEncoding(setter));
}
Then set what strings you want to create dynamic getters and setters for:
+(void)load
{
for(NSString*selectorName in [NSArray arrayWithObjects:#"name", #"anything", #"else", #"you", #"want",nil]){
[self synthesizeForwarder:selectorName];
}
}
That will create getters and setters for any variable name that you add to the array. I'm not sure how well this will work when other classes try to call these methods, the compiler won't see them at compile time so may throw errors when you try to use them. I just combined 2 other
StackOverflow questions into this one answer for your situation.
Dynamic Getters and Setters.
Get current Method name.
As I understand it, you don't want the mental overhead of setObject:forKey: and objectForKey: method calls by the user of this class.
Here is how to get round it. I am leaving a lot of gaps for you to fill in.
Declare the property in the header file, so that callers can use it:
#property NSString *something;
#property NSString *somethingElse;
In the class file itself, declare that you are defining the properties, so that the compiler doesn't get upset:
#dynamic something,somethingElse;
In the class file, implement the methodSignatureForSelector function, like this:
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{if (SelectorIsGetter(aSelector))
return [NSMethodSignature signatureWithObjCTypes:"##:"];
if (SelectorIsSetter(aSelector))
return [NSMethodSignature signatureWithObjCTypes:"v#:#"];
return nil;
}
This will tell the system to call forwardInvocation: for these selectors, and will also tell it the shape of the call that is being made.
Your implementation of SelectorIsGetter and SelectorIsSetter is up to you. You will probably use NSStringFromSelector(aSelector) to get the selector's name, and then look it up in a table of names to see if it matches any of the names of the selectors you are implementing: in this case something and somethingElse for the getters and setSomething: and setSomethingElse: for the setters.
In the class file, implement the forwardInvocation: function, like this:
-(void)forwardInvocation:(NSInvocation *)anInvocation
{if (SelectorIsGetter(anInvocation.selector))
{NSString *s=[self objectForKey:NSStringFromSelector(anInvocation.selector)];
[anInvocation setReturnValue:&s];
return;
};
if (SelectorIsSetter(anInvocation.selector))
{NSString *s;
[anInvocation getArgument:&s atIndex:2];
[self setObjectForKey:UnmangleName(NSStringFromSelector(anInvocation.selector))];
return;
};
[super forwardInvocation:anInvocation];
}
…where UnmangleName is a thoroughly tedious function that takes a string like "setSomething:" and turns it into a string like "something".
If you want to do more than just NSStrings, the extension is reasonably straightforward.
I'm working on a app that can randomize love couples. Just a fun thing, okey!?!? :D
But the problem, or maybe not a problem but a thing that can be much better if I get this thing to be working. In the beginning you need to write in all the names. And thats takes some time... Should I use Core Date? I don't really knows what core data is so I'm not sure. I would love if a god come to me and wrote the full code that can remember an array even if the app and phone shuts down. I have done this in java, is that simpel that it is in java? That would be great!
//Thank, Anton
For Heavy, complex data structures you would want to use core data,
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdTechnologyOverview.html#//apple_ref/doc/uid/TP40009296-SW1
But seeing as you just want to store an array, You should look into NSUserDefaults.
NSUserDefaults will store given data as long as the app is not deleted. You will most likely want to create some kind of custom DataStorage class for this.
#interface DataStorage : NSObject <NSCoding>
#property (nonatomic, strong) NSMutableArray *arrayToStore;
+ (instancetype)sharedInstance;
- (void)save;
#end
Above is the .h file. As you can see, it follows NSCoding protocols. That provides access to methods which allow you to encode data. You will use the save method to write the data to disk.
#import "DataStorage.h"
#implementation DataStorage
#synthesize arrayOfPeople = _arrayToStore;
+ (DataStorage *)sharedInstance
{
static DataStorage *state = nil;
if ( !state )
{
NSData *data =[[NSUserDefaults standardUserDefaults] objectForKey:#"DataStorageKey"];
if (data)
{
state = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
else
{
state = [[DataStorage alloc] init];
}
}
return state;
}
- (id)init{
if (self = [super init]) {
if (!_arrayToStore) {
_arrayToStore = [[NSMutableArray alloc] init];
}
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)decoder
{
self = [self init];
if (self) {
if ([decoder decodeObjectForKey:#"DataStorageArrayToStore"]) {
_arrayToStore = [[decoder decodeObjectForKey:#"DataStorageArrayToStore"] mutableCopy];
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:_arrayToStore forKey:#"DataStorageArrayToStore"];
}
- (void)save
{
NSData *appStateData = [NSKeyedArchiver archivedDataWithRootObject:self];
[[NSUserDefaults standardUserDefaults] setObject:appStateData forKey:#"DataStorageKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#end
Here is the .m file, which pretty much evaluates to see if there is a saved instance of the class, and if not it will create one. [DataStorage sharedInstance]...
when you want to store some data, you will simply make the class available to said file, #import "DataStorage.m and then use
NSString *testData = [NSString stringWithFormat: #"Test Data String"];
[[DataStorage sharedInstance].arrayToStore addObject: testData];
[DataStorage sharedInstance] save];
Specifically, I have two different PlayingCardViewControllers that have two different cardGames. Both SetCardGameViewController and PlayingCardGameViewController inherit from a general CardVC.
Is it better practice to test in the CardVC if the class is either of its subclasses and then complete the actions needed for each subclasses? This would mean that there would be less code, but it seems like it might be confusing. Should best practice depend on just how similar the methods are between the two classes? I was asking with reference specifically using isKindOfClass:
For example if ([self isKindOfClass:[PlayingCardVC1 class]])
Since I was asked for a more specific question here's my more specific question. Would it be better to put the following method in the subclass the way I've defined it and not implement it in the subclasses? Or would it be better practice to set the method in the superclass CardVC just to nil, and simply implement it separately in each of the subclasses?
-(BOOL)insertHighScore:(HighScore*)testedHighScore
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *cardHighScores;
// check if class is SetCardVC
if ([self isKindOfClass:[SetCardGameViewController class]]){
if (![defaults objectForKey:#"setCardHighScores"]){ // if nil
cardHighScores = [[NSMutableArray alloc]init];
[defaults setObject:cardHighScores forKey:#"setCardHighScores"];
}
cardHighScores = [defaults objectForKey:#"setCardHighScores"];
}
// check if class is PlayingCardVC
else if([self isKindOfClass:[PlayingCardGameViewController class]]){
// completely ignored this thing
if (![defaults objectForKey:#"playingCardHighScores"]){ // if nil
cardHighScores = [[NSMutableArray alloc]init];
[defaults setObject:cardHighScores forKey:#"playingCardHighScores"];
}
NSLog(#"finding defaults count == %lu",(unsigned long)[(NSMutableArray *)[defaults objectForKey:#"playingCardHighScores"]count]);
cardHighScores = [defaults objectForKey:#"playingCardHighScores"];
}
//... rest of the code
Tommy's solution is a good one. Here's an alternative solution.
Declare the method in the superclass to take the key as a parameter. Then call the superclass method from the subclasses with different keys. The superclass implementation would look like this
- (BOOL)insertHighScore:(HighScore *)testedHighScore forKey:(NSString *)key
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *cardHighScores;
if (![defaults objectForKey:key]){
cardHighScores = [[NSMutableArray alloc]init];
[defaults setObject:cardHighScores forKey:key];
}
cardHighScores = [defaults objectForKey:key];
// ... rest of code
}
The subclass implementation would look like this
- (BOOL)insertHighScore:(HighScore *)testedHighScore
{
return [super insertHighScore:testedHighScore forKey:#"setCardHighScores"];
}
In general, code specific to the subclass goes in the subclass implementation, code common to all subclasses goes into the superclass implementation, and you can pass some subclass-specific information to the superclass through parameters. In the example above, the superclass doesn't need to know anything about the subclasses. All it knows is that the subclasses will give it a key to look up in NSUserDefaults.
Is it better practice to test in the CardVC if the class is either of
its subclasses and then complete the actions needed for each
subclasses?
No. That's called procedural programming.
The runtime has conditionality built into it. When you do something like:
[instance description]
... figuring out exactly which implementation of description to call based on the type of instance is automatic. So if you do something thing:
if([self isKindOfClass:[A class]])
{
... path A ...
}
if([self isKindOfClass:[B class]])
{
... path B ...
}
if([self isKindOfClass:[C class]])
{
... path C ...
}
// etc
... what you're doing is reimplementing what's already built into the runtime, but less flexible, and in an uglier and more verbose way. What you should have written was:
[self doThing]
... and let the subclasses do their own thing if and only if they want to.
So the question boils down to: is it better practice to reimplement what already exists but less elegantly? No, no it isn't.
As to your specific question, you'd probably do this:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *cardHighScores;
NSString *cardHighScoresKeyName = [self cardHighScoresKeyName];
if (![defaults objectForKey:cardHighScoresKeyName]){ // if nil
cardHighScores = [[NSMutableArray alloc]init];
[defaults setObject:cardHighScores forKey:cardHighScoresKeyName];
}
cardHighScores = [defaults objectForKey:cardHighScoresKeyName];
Or even:
...
cardHighScores = [defaults objectForKey:cardHighScoresKeyName];
if (!cardHighScores){ // if nil
cardHighScores = [[NSMutableArray alloc]init];
[defaults setObject:cardHighScores forKey:cardHighScoresKeyName];
}
Then implement - (NSString *)cardHighScoresKeyName on the subclasses.
(EDIT: though probably you want [[defaults objectForKey:cardHighScoresKeyName] mutableCopy]; if you put an array into the defaults then read it back you'll get a regular array — doesn't matter whether the original was mutable or not)
I have a bunch of activities that are specific to age groups and genders (not trying to be agist or sexist here, just some groups are more likely to take part in these activities so I am trying to suggest them using tags)
I basically need an array that would store this information.
I want a multidimensional array that essentially looks like this:
["Playing Video Games", 10, 24, "male"],
["Putting on Makeup", 14, 50, "female"],
["Sleeping", 0, 100, "both"]
["Activity name string", age lower limit, age upper limit, "genders allowed"];
How can I create this in iOS?
I'll be storing it in the userDefaults.
Objective-C is an object-oriented programming language. So, you need to create a custom class called, maybe 'Person' and then add the required properties.
For example, the custom class's .h file you require will be something like :
#interface Person : NSObject
#property (nonatomic, assign) NSString *activity;
#property (nonatomic, assign) NSString *sex;
#property int ageLowerLimit;
#property int ageUpperLimit;
#end
Then you can manage such objects by first,
Importing this custom class in your code :
#import "Person.h"
And then creating a new Person type object :
Person *firstPerson = [[Person alloc] init];
[firstPerson setActivity : #"Sleeping"];
[firstPerson setSex : #"Male"];
[firstPerson setAgeLowerLimit : 0];
[firstPerson setAgeUpperLimit : 100];
To store them you could use CoreData or just the good old NSUserDefaults.
Here's how to go about the NSUserDefaults approach :
You first store the various Person objects in an NSMutableArray, then you synchronise the defaults :
NSMutableArray *people = [[NSMutableArray alloc] init];
[people addObject : firstPerson];
NSUserDefaults *defaults = [NSUserDefaults standardDefaults];
[defaults setObject:people forKey:#"PEOPLE"];
[defaults synchronise];
To use these objects later, do this :
NSUserDefaults *defaults = [NSUserDefaults standardDefaults];
NSMutableArray *savedPeople = [defaults objectForKey:#"PEOPLE"];
Person *person1 = [savedPeople objectAtIndex:0];
Robert is right and u should use CoreData.
There is an nice [Core Data Tutorial][1] which explains the basics.
WHile using UserDefaults you can store your Data in an Array
[[NSUserDefaults standardUserDefaults] setObject:myArray forKey:#"myArray"];
I want to store data in iOS for globally, like session data in web. What is the best approach other than sqlite?
You can write basic types like NSNumber, NSString, NSArray, NSDictionary, etc directly into the NSUserDefaults. These will be automatically saved/loaded between app sessions.
NSString* myData = #"someValue";
[[NSUserDefaults standardUserDefaults] setObject:myData forKey:#"myData"];
For more complex data types you can take advantage of NSCoder and the NSCoding protocol to easily make your classes serializable.
The code in the answer here may be helpful.
Save own Class with NSCoder
You need to use NSUSERDefault its very easy to handle.
You can save NSString,NSDictionaray ,NSnumber in NSUserDefault like this..
// Store Array values
NSMutableArray *array = [NSMutableArray array];
[[NSUserDefaults standardUserDefaults] setObject:array forKey:#"array"];
// Stroe String to nsuserDefault
NSString *str=#"ABC";
[[NSUserDefaults standardUserDefaults] setObject:str forKey:#"value"];
You can use NSUserDefaults for that.
For saving data you can use this code
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:#"Dilip" forKey:#"firstName"];
[defaults setObject:#"Manek" forKey:#"lastname"];
[defaults setInteger:24 forKey:#"age"];
[defaults synchronize];
And for retrieving data use this code
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *firstName = [defaults objectForKey:#"firstName"];
NSString *lastName = [defaults objectForKey:#"lastname"];
int age = [defaults integerForKey:#"age"];
NSString *ageString = [NSString stringWithFormat:#"%i",age];
You can also store NSDictionary, NSArray, or NSData as object in NSUserDefault.For more information take a look at this tutorial.
another way to pass data Between viewController is like this.
Suppose we have Two ViewController
-FirstViewController
-SecondViewController
Now if i want to pass a string from First to second ViewController thanfirst create Property of that string in secondViewcontroller
#import <UIKit/UIKit.h>
#interface SecondViewcontroller : UIViewController
#property (strong, nonatomic) NSString *strFromFirst;
#end
Synthesize it in .m file. after that in firstViewController when you push view controller Send string to second Viewcontroller
SecondViewcontroller * vc = [[SecondViewcontroller alloc] initWithNibName:#"SecondViewcontroller" bundle:nil];
// Pass the selected object to the SecondViewcontroller.
fraudluntReportViewController.strFromFirst = #"Dilip";
[self.navigationController pushViewController:vc animated:YES];
This will send the string from FirstViewController to SecondViewController.
Use NSUserDefaults.
NSUserDefaults is great for saving samm data like scores, login information, program state. You dont require database knowledge and its easy to learn and use.
Here is the documentation:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
Here is a good tutorial:
http://www.icodeblog.com/2008/10/03/iphone-programming-tutorial-savingretrieving-data-using-nsuserdefaults/
Edit:
Although, based on your comment it seems that you just want to pass data between ViewControllers.
One way :
Lets suppose you want to pass NSString myString from ViewControllerA to ViewControllerB.
Then create a property like this in ViewControllerB.
#property (strong, nonatomic) NSString *passedString;// strong if you are using RC, ow retain
In ViewControllerA.m , when you are allocating, initiating ViewControllerB, then
ViewControllerB *viewControllerB = [[ViewControllerB alloc]init];
viewControllerB.passedString = myString;
Another Way: (more of a global variable type way)
You can declare a property in AppDelegate.h
#property (strong, nonatomic) NSString *passedString;
In ViewControllerB, you can create AppDelgate object and access the property:
AppDelegate *app = [[UIApplication sharedApplication]delegate];
NSString *passedString = app.passedString;
If you have limited data to store feel free to use NSUserDefaults.
Apple Reference for NSUserDefaults
for example you need to store some string(say name) in to user defaults.
NSString *name = "Your Name";
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:name forKey:#"name"];
[defaults synchronize];
IMPORTANT here is, once you done with setObject for key, you have to call synchronize method so that these changes get stored in User Defaults
for accessing the same firstName string
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[defaults objectForKey:#"name"];