Accessing variable values from one view in another - iphone

I'm having some trouble understanding how variable values are passed from one view to another. I have a UITextField in the firstview that the user enters a number into. When the user taps a button, that number is multiplied by 2 and the result is displayed on a UILabel in the second view. This is what I have thus far
FirstViewController.h
#interface FirstViewController : UIViewController{
UITextField *numberTextField;
NSNumber *aNumber;
}
#property (nonatomic, retain) IBOutlet UITextField *numberTextField;
#property (nonatomic) NSNumber *aNumber;
-(IBAction)calculate;
#end
FirstViewController.m
#implementation FirstViewController
#synthesize numberTextField, aNumber;
-(double)doubleNumber{
double number = [numberTextField.text doubleValue] * 2;
return number;
}
-(IBAction)calculate{
self.aNumber = [NSNumber numberWithDouble:[self doubleNumber]];
}
//more default code continues below
SecondViewController.h
#import "FirstViewController.h"
#interface SecondViewController : FirstViewController{
UILabel *numberLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *numberLabel;
#end
SecondViewController.m
#implementation SecondViewController
#synthesize numberLabel;
- (void)viewDidLoad
{
[super viewDidLoad];
numberLabel.text = [NSString stringWithFormat:#"%#",aNumber];
}

Best and Easy Way to store value globally
set you object with your keyword
[[NSUserDefaults standardUserDefaults] setObject:#"Ajay" forKey:#"name"];
than get that object any where in you project
NSString *name = [[NSUserDefaults standardUserDefaults] objectForKey:#"name"];

You should accomplish what you want by using a segue. Create a segue in your storyboard and then call it in your firstviewcontroller with - (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender. Then to pass data, import your secondviewcontroller.h file with a property for the value you want to pass and setup - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender.
In that method you can pass things by using [segue.destinationViewController ###call the setter for the property in your secondViewController.h file###];
If this isn't clear, or you need more help just let me know.

I'm assuming that the FirstViewController is instantiating the SecondViewController. If that is so, then you just pass aNumber to the SecondViewController using an additional property:
// add an additional property to the SecondViewController
#property (nonatomic, retain) NSNumber *aNumber;
When you instantiate the SecondViewController inside the FirstViewController, you just pass that value to the SecondViewController before you load it:
// inside FirstViewController
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.aNumber = aNumber;
// inside SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
numberLabel.text = self.aNumber;
}

Mmm... Pay attention to not confuse views and viewControllers!!!
A viewController can manage more than a view. For example in your code you have a UITextField, a UILabel and probably a UIButton. These are all views that are managed by two viewsController (FirstViewController and SecondViewController).
As long as you have so few views to work with you can use just one viewController and pass the value you want to your UILabel directly:
- (void)calculateAndPassValue
{
aNumber = [NSNumber numberWithDouble:[self doubleNumber]];
numberLabel.text = [NSString stringWithFormat:#"%#",aNumber];
}
Otherwise, if your goal is passing variable values from one viewController to another. Well... There are many ways you can obtain that, for example:
Creating an ivar.
Using a singleton.
Saving your data in NSUserDefault.
Creating a database on disk.
First and second cases are good if you need to manage your data while your app is running. Third and fourth if you want to memorize your data for future use and retrieve them at next start up.
Try to search keys like ivar, singleton, NSUserDefault and you'll find many discussions and lines of sample code.

Related

How to send data from UItextfields of one viewcontroller to new view controller? [duplicate]

I am a bit stuck on trying to pass data from two UITextfields on one viewcontroller to another viewcontroller. Basically I got the items below:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
IBOutlet UITextfield *Textfield1;
IBOutlet UITextfield *Textfield2;
}
-(IBAction)GoNextView:(id)sender;
#end
ViewController.m
#interface ViewController ()
#end
#implementation ViewController
(IBAction)GoNextView:(id)sender {
SecondView *second = [[SecondView alloc] initWithNibName:nil bundle:nil];
[self presentViewController:second animated:YES completion:NULL];
}
- (void)viewDidLoad {
[super viewDidLoad];
}
SecondView.h
#import <UIKit/UIKit.h>
#interface SecondView : UIViewController {
IBOutlet UILabel *ShowTextfield1;
IBOutlet UILabel *ShowTextfield2;
}
-(IBAction)GoBack:(id)sender;
#end
SecondView.m
#interface SecondView ()
#end
#implementation SecondView
- (IBAction)GoBack:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
}
What I want is, that when the button GoNextView is pressed it should pass the data in the UITextfield to the SecondView. And the go to the next page. The data should now be displayed in the two Labels on the SecondView. I've been struggling with this for many hours now and its killing me. I know I have to use some NSString and #property(nonatomic, retain) NSString *asdas. But I simply can't make it work. So based on the above code how do I pass data from the two UITextfield to the two labels on the next view?
Instead of navigating to the second view through a function, use Storyboard Segues. Create a storybaord application. To Create a segue you need a navigation view controller. You can do that by the following steps.
Select the first view controller and go to Editor -> Embed In -> Navigation Controller.
Then Ctrl+Click on the "GoNextView" button, and drag and drop in the SecondView.
You will get three options: push, model, custom. Click push then a segue will be created between these two views.
Click that segue and click the "Show the Attribute Inspector" on the right side property window. Now name it as "connector" or which ever name you prefer.
Now, in SecondView.h create two strings,
#property (nonatomic, retain) NSString *str1;
#property (nonatomic, retain) NSString *str2;
and synthesize them in SecondView.m.
Lets name your UITextFields as "text1" and "text2" which are in your ViewController. Go to the ViewController.h and add #import "SecondView.h"
In ViewController.m do the following,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"connector"])
{
ViewController *VC = [segue destinationViewController];
VC.str1 = text1.text;
VC.str2 = text2.text;
}
}
Now you can display these strings in your SecondView. In Secondview.m,
label.text = str1;
and it will be displayed.
Use NSUserDefaults or the normal synthesising common interface variables. For example,
NSUserDefaults
From sender's view controller,
NSString *text=textField1.text;
NSUserDefaults *prefs=[NSUserDefaults standardUserDefaults];
[prefs setObject:text forKey:#"text1value"];
And you can get the value from any view controller as,
NSUserDefaults *prefs=[NSUserDefaults standardUserDefaults];
NSString *received string= [prefs stringForKey:#"text1value"];
Normal assigners,
I believe you must be using performsegue to navigate view controllers. There is a delegate method called "prepareforsegue" and you can assign the textfield values into the interface variables. For example,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"seguename"]) {
destViewController *destViewController = segue.destinationViewController;
destViewController.name = #"some text";
}
}
In the receiver's view controller, getter variable is actually defined as,
In .h file, #property(nonatomic, strong) NSString *name;
In .m file, Don't forget to synthesis the variable after implementation
#implementation destViewController
#synthesize name;
Hope it helps!

I'm trying to pass a string from my first ViewController to my second ViewController but it returns NULL

In my first view controller I have 3 input fields each of them take the user input into and saves it into a string such as: address, username and password as NSUserDefaults. This part works fine.
In my second view controller I'm trying to take the 3 strings from first controller (address, username and password) create a html link based on the 3 strings. I've tried many ways to access the 3 strings with no luck, the result I get is NULL.
Here is my code:
//.h file - first view controller with the 3 input fields CamSetup.h
#import <UIKit/UIKit.h>
#interface CamSetup : UIViewController <UITextFieldDelegate>
{
NSString * address;
NSString * username;
NSString * password;
IBOutlet UITextField * addressField;
IBOutlet UITextField * usernameField;
IBOutlet UITextField * passwordField;
}
-(IBAction) saveAddress: (id) sender;
-(IBAction) saveUsername: (id) sender;
-(IBAction) savePassword: (id) sender;
#property(nonatomic, retain) UITextField *addressField;
#property(nonatomic, retain) UITextField *usernameField;
#property(nonatomic, retain) UITextField *passwordField;
#property(nonatomic, retain) NSString *address;
#property(nonatomic, retain) NSString *username;
#property(nonatomic, retain) NSString *password;
#end
//.m file - first view controller CamSetup.m
#import "CamSetup.h"
#interface CamSetup ()
#end
#implementation CamSetup
#synthesize addressField, usernameField, passwordField, address, username, password;
-(IBAction) saveAddress: (id) sender
{
address = [[NSString alloc] initWithFormat:addressField.text];
[addressField setText:address];
NSUserDefaults *stringDefaultAddress = [NSUserDefaults standardUserDefaults];
[stringDefaultAddress setObject:address forKey:#"stringKey1"];
NSLog(#"String [%#]", address);
}
-(IBAction) saveUsername: (id) sender
{
username = [[NSString alloc] initWithFormat:usernameField.text];
[usernameField setText:username];
NSUserDefaults *stringDefaultUsername = [NSUserDefaults standardUserDefaults];
[stringDefaultUsername setObject:username forKey:#"stringKey2"];
NSLog(#"String [%#]", username);
}
-(IBAction) savePassword: (id) sender
{
password = [[NSString alloc] initWithFormat:passwordField.text];
[passwordField setText:password];
NSUserDefaults *stringDefaultPassword = [NSUserDefaults standardUserDefaults];
[stringDefaultPassword setObject:password forKey:#"stringKey3"];
NSLog(#"String [%#]", password);
}
- (void)viewDidLoad
{
[addressField setText:[[NSUserDefaults standardUserDefaults] objectForKey:#"stringKey1"]];
[usernameField setText:[[NSUserDefaults standardUserDefaults] objectForKey:#"stringKey2"]];
[passwordField setText:[[NSUserDefaults standardUserDefaults] objectForKey:#"stringKey3"]];
[super viewDidLoad];
}
#end
//.h second view controller LiveView.h
#import <UIKit/UIKit.h>
#import "CamSetup.h"
#interface LiveView : UIViewController
{
NSString *theAddress;
NSString *theUsername;
NSString *thePassword;
CamSetup *camsetup; //here is an instance of the first class
}
#property (nonatomic, retain) NSString *theAddress;
#property (nonatomic, retain) NSString *theUsername;
#property (nonatomic, retain) NSString *thePassword;
#end
//.m second view LiveView.m file
#import "LiveView.h"
#interface LiveView ()
#end
#implementation LiveView
#synthesize theAddress, theUsername, thePassword;
- (void)viewDidLoad
{
[super viewDidLoad];
theUsername = camsetup.username; //this is probably not right?
NSLog(#"String [%#]", theUsername); //resut here is NULL
NSLog(#"String [%#]", camsetup.username); //and here NULL as well
}
#end
There are 5 issues in this code:
If you are using ARC, all the "retain" in your #properties should be changed to "strong"
You name your iVars and properties the same thing. (common bad practice)
You are always directly accessing iVars and not properties in your code.
You don't retain your instance of CamSetup in the second object.
The direct cause of your problem: in the second object you've only created a placeholder for a CamSetup instance, you've not created one nor passed one to it! self.camSetup in your second object is empty right now.
Let's go step by step:
First, give your iVars different names from your properties. This is best practice, especially for a beginner! :)
#interface CamSetup : UIViewController <UITextFieldDelegate>
{
NSString *_address;
}
#property(nonatomic, strong) NSString *address;
#end
#implementation CamSetup
#synthesize address=_address;
...
#end
This is important, because you've setup properties, but in your code, you are not using them, you are directly accessing your iVars. Since you've named them the same thing, you might not see this.
Let's look at your first object. Every "address" in your code is going to your iVar and not property. Generally, you want to access the iVars via your properties unless you're sure otherwise. The #synthesize creates a getter and setter method for your iVar that will retain the var because you told it to in your #property statement. However, when you directly access your iVar's you're not going through those accessors and thus the stuff you wrote in your #properties doesn't matter. You could end up misunderstanding a lot of errors and bugs if you aren't clear about this. In your first object this worked anyway because the alloc/init sets a retain on the object, but I noticed you always do this, and that's going to get you into trouble.
Here's what the saveAddress: method would look like using properties:
-(IBAction) saveAddress: (id) sender
{
self.address = [[NSString alloc] initWithFormat:self.addressField.text];
[self.addressField setText:self.address];
NSUserDefaults *stringDefaultAddress = [NSUserDefaults standardUserDefaults];
[stringDefaultAddress setObject:self.address forKey:#"stringKey1"];
NSLog(#"String [%#]", self.address);
}
Next, in your second object you need to set properties for the CamSetup instance! Right now, you just have an iVar.
#import <UIKit/UIKit.h>
#import "CamSetup.h"
#interface LiveView : UIViewController
{
NSString *_theAddress;
NSString *_theUsername;
NSString *_thePassword;
CamSetup *_camSetup; //here is an instance of the first class
}
#property (nonatomic, retain) CamSetup *camSetup; // in synthesize we'll specify that this property uses the _camSetup iVar
#property (nonatomic, strong) NSString *theAddress;
#property (nonatomic, strong) NSString *theUsername;
#property (nonatomic, strong) NSString *thePassword;
#end
The implementation:
#import "LiveView.h"
#interface LiveView ()
#end
#implementation LiveView
#synthesize camSetup = _camSetup;
#synthesize theAddress = _theAddress;
#synthesize theUsername = _theUsername;
#synthesize thePassword = _thePassword;
- (void)viewDidLoad
{
[super viewDidLoad];
self.theUsername = self.camSetup.username; //this is probably not right?
// well, it's better now, but where is camSetup coming from??? it's undefined now
NSLog(#"String [%#]", self.theUsername); //resut here is NULL
NSLog(#"String [%#]", self.camSetup.username); //and here NULL as well
}
#end
We've created an iVar and property pair that will hold a pointer to a CamSetup instance and will retain that pointer (if we set it using the property). However, where is that CamSetup instance being created? Where do you alloc/init it?
There are many possible answers to this question. If CamSetup had getters for address, username, password that read them back in from your user defaults, then all you'd have to do is alloc/init a CamSetup and set it to camSetup. However, right now your first object has no functionality to retrieve the saved data so we can't do that. (still, this is the solution I'd hope you'd implement).
You might be initializing both of these in your app delegate? However, if you are using storyboard then likely it is initializing these object for you when it initializes your interface. In this case, in your appDelegate app has finished launching... method, you'll have to retrieve pointers to these instances, then the camSetup property on your second object, to point to the first. To tell you how to do this, we'd have to know detailed specifics of your app. Still, this wouldn't be doing it the best way.
Best practice would be to create an object which saves and retrieves these data from user defaults for you. This future proofs your implementation should you later want to change the way you store these data. You'd just change the way they are stored/retrieved within their class.
Your problem is here:
CamSetup *camsetup; //here is an instance of the first class
You aren't doing anything to make camsetup refer to the same instance of the CamSetup class that is taking input from the user. The camsetup variable is never initialized, hence it's NULL, hence any properties you try to retrieve from it will also be NULL.
How exactly you'd fix this depends on the structure of your program. One possibility is to have whatever code is creating the LiveView controller set the camsetup value. For example:
LiveView *liveViewController = [LiveView alloc] initWithNibName:#"LiveView" bundle:nil]];
liveViewController.camsetup = camSetupController;
(you'd need to make camsetup a property to do this).
BUT, from a design standpoint, having the one view controller have a reference to the other is probably the wrong way to go about solving this problem -- it introduces unnecessary dependencies between the two controllers. For example, say you later decide to make it possible to go directly to the LiveView controller upon program launch, using a saved name/password; you can't do that if LiveView depends on getting its input from a CamSetup object.
So, a better approach might be to have LiveView take its input from NSUserDefaults, and/or by having the code that's calling LiveView set the username/password properties.
-- edit --
For example, retrieve the data from the user defaults like:
self.address = [[NSUserDefaults standardUserDefaults] objectForKey:#"stringKey1"];
Is the camsetup initialized? If not -- initialize it first.
There are many ways to do this, most of which depend on how the two controllers are related to each other (like how are you going from the first to the second).
However, in your case you don't need to pass the string at all, since you are saving them in user defaults. Just read the values of those defaults in your second controller.
Hi i got your problem just do one thing.
When you are setting value in NSUserDefaults it need synchronization so just synchronize it.
[stringDefaultUsername synchronize];
And retrieve data using
NSString *username = [[NSUserDefaults standardUserDefaults] objectForKey:#"stringKey2"];
Follow apple NSUserDefaults Class Reference for more info

Difficulty accessing objects in another view controller

I'm setting a string in a view controller called ViewController and trying to access it somewhere else. This is the code:
ViewController.h
NSString *string;
...
#property (retain) NSString *string;
ViewController.m
#synthesize string;
...
-(void)viewDidLoad {
...
string = #"Test";
}
OtherViewController.m
#import "ViewController.h"
...
-(void)viewDidLoad {
ViewController *vc;
vc = [[ViewController alloc] init];
NSLog(#"String: %#", vc.string);
}
However, the log is showing: String: (null). What am I doing incorrectly? Thanks.
The viewDidLoad of ViewController is only called when the view is loaded. The view is lazily loaded when required e.g. when a call to vc.view is made.
I'm not sure what you are trying to achieve but this certainly seems like a code smell to me.
As #Fscheidl points out you are creating a new instance and not accessing an existing instance so this may add to your problem. I still believe your main issue is that you assume viewDidLoad is being called just by creating the viewController, which is not the case
edit : it doesn't necessarily need to be an NSObject class, if you want to, you could also do this on your viewController class, just be sure to also include
-(id)init
on your header
---- end of edit
if you're trying to make a class that's accessible to another view controller, why not try NSObject instead of view controller (considering you only need to take that string value)
for instance, lets call that viewController class "global" class
so at global.h, you put up
#import <Foundation/Foundation.h>
#interface GlobalVar : NSObject
#property (nonatomic, strong) NSString *myString;
-(id)init;
#end
and then, at global.m you put up
#import "GlobalVar.h"
#implementation GlobalVar
#synthesize myString;
-(id)init
{
self = [super init];
if(self)
{
myString = [[NSString alloc]initWithFormat:#"the String"];
}
return self;
}
#end
after this, everytime you need to access the "myString" object that contained in global class, you could put up
at header :
#import "GlobalVar.h"
...
...
#property (nonatomic, strong) GlobalVar *globalVar;
at implementation file :
#synthesize globalVar;
...
...
self.globalVar = [[GlobalVar alloc]init];
NSString *theString = globalVar.myString;
NSLog(#"content of my string is : %#",theString);
there you go ;)
You do create a new instance of ViewController by calling [[ViewController alloc] init]; This instance hasn't had string even set. You have to access that exact instance of ViewController.
If you create the instance of OtherViewController directly from ViewController, you can add the following to OtherViewController.h:
#import "ViewController.h"
#property (nonatomic, retain) ViewController *previousViewController
When creating the OtherViewController, you can then set:
//alloc and init instance of OtherViewController
myOtherViewController.previousViewController = self;
In your viewDidLoad: method, you can then access your string as follows:
NSLog(#"String: %#", previousViewController.string);

NSDictionary setting to nil when passed to another class (IOS)

I am passing an NSDictionary object from one view class to another as I transition from a table view to a normal view to show details:
Passing Controller:
[tweetController setTweet:tweet];
Receiving Controller.h:
#interface TweetViewController : UIViewController {
NSDictionary *tweet;
}
#property (nonatomic, retain) NSDictionary *tweet;
Receiving Controller.m:
#implementation TweetViewController
#synthesize tweet = _tweet;
I then try to use this information to set the properties of some fields in my view:
- (void)viewDidLoad
{
[super viewDidLoad];
tweetLabel.text = [_tweet objectForKey:#"text"];
}
The result is a blank label and if I inspect the value of _tweet at this stage it is nil.
I originally had a method which set the value of tweet which I called at the same location as I am now setting the value. If I inspected the value at this stage it was fine.
I presume that the automagic setter through #synthasize is working, but somewhere else the value is being lost.
Sorry this is my first objective C anything! Thanks for any help in advance.
You are using your "tweet" instance variable, whereas the "tweet" property is synthesized to the "_tweet" variable.
You are probably calling the setTweet method after viewDidLoad executes.
I usually pass this kind of thing into a custom init method.
Alternatively, you could do the set before pushing the detail VC onto the nav stack.
Are you sure that tweetLabel isn't nil?
I've made a few corrections & optimisations to your code. You don't need to declare ivars in the header file anymore, they are generated automatically by #synthesize
- (void)dealloc; is only needed if you're not using ARC.
//.h
#interface TweetViewController : UIViewController
#property (strong, nonatomic) NSDictionary *tweet;
#property (strong, nonatomic) IBOutlet UILabel *tweetLabel
#end
//.m
#implementation TweetViewController
#synthesize tweet = _tweet;
#synthesize tweetLabel = _tweetLabel;
- (void)viewDidLoad {
[super viewDidLoad];
self.tweetLabel.text = [self.tweet objectForKey:#"text"];
}
- (void)dealloc {
[_tweet release];
[_tweetLabel release];
[super dealloc];
}
#end
Note: strong is equivalent to retain
To expand on #Rayfleck's answer, since you are new to Objective-C, your custom init method could look like this:
In TweetViewController.h:
- (id)initWithTweet:(NSDictionary*)tweet;
In TweetViewController.m:
- (id)initWithTweet:(NSDictionary*)tweet
{
self = [super init];
if (self) {
_tweet = tweet;
}
return self;
}
and then in your passing controller you'd allocate and initialize like this:
TweetViewController *tvc = [[TweetViewController alloc] initWithTweet:myTweet];

How to copy text from one ViewController to another?

I'm writing a little quiz application. So I have a first view, where I ask a person to enter his/her name and a button which is the IBAction to go the next view with the first question. In the end, after a person has answered all questions, comes the congratulations view, where I want to copy the name, that was entered on the first view. Say there will be a phrase "Well done, John!" How can I do it?
On the first view(FirstViewController) I made a textfield
IBOutlet UITextField *text1;
And on the last view in .h:
IBOutlet UITextField *text2;
and
-(IBAction)copy:(id)sender;
And in .m:
- (IBAction)copy:(id)sender
{
[text2 setText:[text1 text]];
}
and
#import "FirstViewController.h"
But it says identifier text1 is undefined
I don't know what else to do...
You can override the
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
method of last view controller with something like:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString*)userName
(don't forget to declare this method in your .h file.)
Now while initializing your last view controller, you can pass the name of the user to last view controller.
In the implementation of the this overriden method in last view controller, copy this name in some local variable. and use it.
Hope this will solve your problem.
In your firstView add NSString with its property
Something like this in .h file
NSString *username;
and
#property (nonatomic , retain) NSString *username;
in .m file
username = text1.text;
In LastView
im .m file
#import "FirstView.h"
And where ever you want username try this
FirstView *firstview = [[FirstView alloc] init];
text2 = firstview.username;
Hope it works..!!
Override the init method of SecondViewController as follows
-(id)initWithUsername:(NSString *)username
{
//create instance and then do
text2.text = username ;
}
And in the FirstViewController , where you create the instance of SecondViewController init it using the above
SecondViewController *second = [[SecondViewController alloc] initWithUsername:text1.text];
For passing value from one VC to other you have to do following code :
First declare local variable in next view where you want to move like.
#property(nonatomic, strong) NSString *personName;
Now prepare object of second VC in the first VC.m file on button click action. But before that must set storyboard identifier of that second VC in storyboard.
SecondViewController *obj = (SecondViewController *) [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
obj.personName = self.txtUserName.text;
Now go on there on second VC and do whatever you want.
Note : Here you don't need to used userdefaults, OR prepared init methods with parameters, OR using delegates etc.
The best way to do this would be taking the variables you need on various views and handling them on the delegate since the delegate has access to everything. Making a Global variable is never advisable that is what the delegate is for.
You can refer to this question that treats the same issue: Passing data between view controllers
You can add a NSString member (along with a property) in the application delegate class.
/// AppDelegate.h, or whatever it's called in your application
#interface AppDelegate : NSObject <UIApplicationDelegate> {
NSString *username;
// <rest of the members>
}
...
#property (nonatomic, retain) NSString *username;
#end
/// AppDelegate.m
#implementation AppDelegate
#synthesize username;
#end
/// FirstViewController.m
-(void)viewDidDissappear:(BOOL)animated{
[super viewDidDissappear:animated];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.username = text1.text;
}
/// LastViewController.m (or whatever it's called)
-(void)viewDidLoad{
[super viewDidLoad];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[text2 setText:[NSString stringWithFormat:#"Well done %#", appDelegate.username]];
}
Ok, so for everyone to be happy, you can (and are suggested to) create your own singleton class in which you can hold non-persistent global variables, and use in the code above instead of the application delegate.
/// SharedData.h
#interface SharedData: NSObject {
NSString *username; /// or instead you can have a NSMutableDictionary to hold all shared variables at different keys
}
+(SharedData *)sharedInstance;
#property(nonatomic, retain) NSString *username;
#end
/// SharedData.m
#include "SharedData.h"
static SharedData *_sharedInstance=nil;
#implementation SharedData
#synthesize username;
+(SharedData)sharedInstance{
if(!_sharedInstance){
_sharedInstance = [[SharedData alloc] init];
}
return _sharedInstance;
}
#end
I would make use of NSUserDefaults to set the user's name when they enter it. Then, in your last view controller, just query NSUserDefaults again for the name you want. Granted, this is still global state, but NSUserDefaults is meant for this sort of purpose:
// In the first view controller
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:#"John Doe" forKey:#"XXUserNameKey"]; // This should actually be an extern for your app to use globally
// In the last view controller
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *userName = [userDefaults stringForKey:#"XXUserNameKey"];
Adding state to your app delegate is an abuse of the design pattern.
Also, I should clarify that NSUserDefaults should not be used as a general-purpose storage container. Its intent is for common, shared data like user names, preferences, etc. Something like the name a user enters at the beginning of a game seems to fall within the usage pattern.