I have 2 views that are sharing the same class files (.h and .m). In the first view, I have a UIPicker with a list of items and a button. If the user clicks the button, I want my second view to come up with the appropriate Picture (based on the item that was selected in the UIPicker).
My thinking was to set an NSString in the first view based on the selected item. Then when the user clicks the button to push the second view onto the screen, i could pass that string with the new view. I've been "googling" for awhile but I can't seem to wrap my finger around it. If it matters, I am using a Navigation Controller. Here is the code that is executed on the button click:
-(IBAction) viewPictures{
ViewControllerClass *sView = [[ViewControllerClass alloc] initWithNibName:#"ViewController2XIB" bundle:nil];
[self.navigationController pushViewController:sView animated:YES];
}
You can either add an NSString * property to the ViewControllerClass and set it after you init it (this would be the easiest), or you can create your own init method that takes a string and sets it there.
Option 1:
(place this in your .h file)
#interface ViewControllerClass : UIViewController {
NSString *someString;
}
#property (nonatomic, copy) NSString *someString;
#end
(Then in your .m file)
#implementation ViewControllerClass
#synthesize someString;
#end
Alter your code from above to this:
-(IBAction) viewPictures{
ViewControllerClass *sView = [[ViewControllerClass alloc] initWithNibName:#"ViewController2XIB" bundle:nil];
sView.someString = #"Whatever String you want";
[self.navigationController pushViewController:sView animated:YES];
}
Option 2:
(place this in your .h file)
#interface ViewControllerClass : UIViewController {
NSString *someString;
}
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle someString:(NSString *)SomeString;
#end
(Then in your .m file)
#implementation ViewControllerClass
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle someString:(NSString *)SomeString
{
if(self = [super initWithNibName:nibName bundle:nibBundle]) {
someString = [SomeString copy];
}
return self;
}
#end
Alter your code from above to this:
-(IBAction) viewPictures{
ViewControllerClass *sView = [[ViewControllerClass alloc] initWithNibName:#"ViewController2XIB" bundle:nil someString:#"Whatever String you want"];
[self.navigationController pushViewController:sView animated:YES];
}
Put a NSString in the .m that shares these 2 views, like Chris said.
In the method that responds to the button click pass the string from the uipicker to the NSString you created and then pass it to the view 2.
Related
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!
In my Application,
There are two different views ItemList And ItemSearch.
In ItemList file I have one NsMutableArray with name tblItem. I want pass data in tblitem from the Itemsearch page.
How can I do this?
You can make use of properties as follows:
1.Create a property in ItemList.h of tblItem as,
#property(nonatomic, retain) NSMutableArray *tblItem;
then synthesize it in ItemList.m,
#synthesize tblItem;
When you are navigating from ItemSearch to ItemList ie when you are initializing ItemList just provide tblItem the required values as,
ItemListObj.tblItem = theSearchedArray;
Declare an NSMutableArray as property in the SecondViewController and assign the array at the time you are pushing or presenting the SecondViewController from the FirstViewController.
#interface SecondViewController : UIViewController
{
NSMutableArray *aryFromFirstViewController;
}
#property (nonatomic,retain) NSMutableArray *aryFromFirstViewController;
#end
At the implementation, synthesize the property
#implementation SecondViewController
#synthesize aryFromFirstViewController;
#end
At the header of the FirstViewController import the SecondViewController
#import "SecondViewController.h"
At implementation of the FirstViewController, add the code like below in where you wrote the code to present or push the SecondViewController
#implementation FirstViewController
- (void) functionForPushingTheSecondViewController
{
SecondViewController *objSecondViewController = [[SecondViewController alloc] initWithNIBName: #"SecondViewController" bundle: nil];
objSecondViewController.aryFromFirstViewController = self.myAryToPass;
[self.navigationController pushViewController:objSecondViewController animated: YES];
[objSecondViewController release];
}
#end
Please don't forget to release the aryFromFirstViewController at dealloc method of SecondViewController, otherwise it will leak because we retained it. I'l feel good if i come to know that this helped you in someways. Enjoy.
It depends on your need. You can use Singleton class for sharing of your variables between different classes. Define all variable which you wants share in your DataClass.
in .h file (where RootViewController is my DataClass, replace name with your new class)
+(RootViewController*)sharedFirstViewController;
in .m file
//make the class singleton:-
+(RootViewController*)sharedFirstViewController
{
#synchronized([RootViewController class])
{
if (!_sharedFirstViewController)
[[self alloc] init];
return _sharedFirstViewController;
}
return nil;
}
+(id)alloc
{
#synchronized([RootViewController class])
{
NSAssert(_sharedFirstViewController == nil,
#"Attempted to allocate a second instance of a singleton.");
_sharedFirstViewController = [super alloc];
return _sharedFirstViewController;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
after that you can use your variable in any other class like this
[RootViewController sharedFirstViewController].variable
Hope it's help you:)
I have a view with a view controller and when I show this view on screen, I want to be able to pass variables to it from the calling class, so that I can set the values of labels etc.
First, I just tried creating a property for one of the labels, and calling that from the calling class. For example:
SetTeamsViewController *vc = [[SetTeamsViewController alloc] init];
vc.myLabel.text = self.teamCount;
[self presentModalViewController:vc animated:YES];
[vc release];
However, this didn't work. So I tried creating a convenience initializer.
SetTeamsViewController *vc = [[SetTeamsViewController alloc] initWithTeamCount:self.teamCount];
And then in the SetTeamsViewController I had
- (id)initWithTeamCount:(int)teamCount {
self = [super initWithNibName:nil bundle:nil];
if (self) {
// Custom initialization
self.teamCountLabel.text = [NSString stringWithFormat:#"%d",teamCount];
}
return self;
}
However, this didn't work either. It's just loading whatever value I've given the label in the nib file. I've littered the code with NSLog()s and it is passing the correct variable values around, it's just not setting the label.
Any help would be greatly appreciated.
EDIT: I've just tried setting an instance variable in my designated initializer, and then setting the label in viewDidLoad and that works! Is this the best way to do this?
Also, when dismissing this modal view controller, I update the text of a button in the view of the calling ViewController too. However, if I press this button again (to show the modal view again) whilst the other view is animating on screen, the button temporarily has it's original value again (from the nib). Does anyone know why this is?
When a view controller is being initialized, inside the initWithNibName method, the views that reside in the view controller aren't yet initialized and you can't set their properties yet. Do whatever you need that is view based in the "viewDidLoad" method.
I am not a pro but this may help you.
In the header view1.h, declare the desired property:
// view1.h
#interface view1 : UIViewController {
NSString *passingVariable;
}
#property (nonatomic, strong) NSString *passingVariable;
#end
and then in the implementation of view1, synthesize the variable:
// view1.m
#implementation view1
#synthesize passingVariable;
// the rest of the implementation
#end
and, finally in the implementation of the other view controller, view2:
// view2.m
#import "view1.h"
#implementation view2
-(IBAction)changeview
{
view1 *myview = [[view1 alloc] init];
myview.passingVariable = #"Hello Variable";
[self.navigationController pushViewController:myview animated:YES];
}
#end
here i am trying to move from view2 to view 1 and also initializing the passingVariable ivar of view1. hope this will help you.
Here i'm passing the ViewController's label text to SecondViewController's Label Text
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
// please make your control on XIB set these IBOutlet's
//I'm not showing how to connect these with XIB
IBOutlet UILabel *lblView;
IBOutlet UIButton *buttonGo;
}
//this is method which will push the view
-(IBAction)buttonGoClickAction:(id)sender;
ViewController.m
-(IBAction)buttonGoClickAction:(id)sender
{
SecondViewController *secondViewObject = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
//before pushing give the text
secondViewObject.string = lblView.text;
[self.navigationController pushViewController:secondViewObject animated:YES];
}
SecondViewController.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController
{
IBOutlet UILabel *labelView;
NSString *string;
}
//set the string property
#property(nonatomic, retain) NSString *string;
#end
SecondViewController.m
#import "SecondViewController.h"
#implementation SecondViewController
//synthesize string here
#synthesize string;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//Here you will get the string
labelView.text = string;
}
Firstly you check that have you attach this label IBOutlet in xib or not if you made it via Interface Builder....
use it like this....
SetTeamsViewController *vc = [[SetTeamsViewController alloc] initWithTeamCount:teamCount];
Take a string variable in .h file and set that string here .. NSSting *str in .h
- (id)initWithTeamCount:(int)teamCount {
self = [super init];
if (self) {
// Custom initialization
str = [NSString stringWithFormat:#"%d",teamCount];
}
return self;
}
and set your label in viewDidLoad: or in viewWillApear:
self.teamCountLabel.text = str;
May this will help you
As said by stavash, control in the xib are created in the view did load. To be more precise, they are created with that line :
[super viewDidLoad];
So, mylabel doesn't exist before that time (it is nil).
The easiest way is to do that :
SetTeamsViewController *vc = [[SetTeamsViewController alloc] init];
[self presentModalViewController:vc animated:YES];
vc.myLabel.text = self.teamCount;
[vc release];
The longer but more correct path is to have a member NSString* in SetTeamsViewController class, to set it to teamCount before showing the window, and in the view did load to put that membre value in your label.
Cdt
It depends on your need. You can use Singleton class for sharing of your variables between different classes. Define all variable which you wants share in your DataClass.
in .h file (where RootViewController is my DataClass, replace name with your new class)
+(RootViewController*)sharedFirstViewController;
in .m file
//make the class singleton:-
+(RootViewController*)sharedFirstViewController
{
#synchronized([RootViewController class])
{
if (!_sharedFirstViewController)
[[self alloc] init];
return _sharedFirstViewController;
}
return nil;
}
+(id)alloc
{
#synchronized([RootViewController class])
{
NSAssert(_sharedFirstViewController == nil,
#"Attempted to allocate a second instance of a singleton.");
_sharedFirstViewController = [super alloc];
return _sharedFirstViewController;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
after that you can use your variable in any other class like this
[RootViewController sharedFirstViewController].variable
Hope it's help you:)
With Storyboards the the right way is to pass the indexPath as sender argument in performSegueWithIdentifier
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"segueIdentifier" sender:indexPath];
}
and to set a property in the destination controller:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString: #"segueIdentifier"]) {
NSIndexPath *indexPath = sender;
DetailViewController *dest = [segue destinationViewController];
dest.usersArray = [self.usersArray objectAtIndex:indexPath.row];
}
}
What I have done whenever I needed another class to have the variables from the previous class I either set up a global class that will store the values incase I need them in more locations or in the interface you can set #public variables. These variables can be set using the controller that you created for the next view as such.
controller->pub_var1 = val1;
controller->pub_var2 = val2;
This will be done before you pass the view to the root controller or just before you call the next view. You will need to #import "class.h" so that you can access those public variables.
I can show code if this is not clear
I have two views with navigation controller: first view, there are empty text fields while the second view is a table view where the user can select a row. At the touch of a row there is an action that sets a value to a text field of the first view. Unfortunately when I go back to the first view field is not set.
This is my code:
FirtViewController.h
#interface FirstViewController : UIViewController
{
UITextField *firstField;
UITextField *secondField;
}
#property(nonatomic, retain) IBOutlet UITextField *firstField;
#property(nonatomic, retain) IBOutlet UITextField *secondField;
#property(copy) NSString *selectedRow;
-(IBAction)showTable:(id)sender
FirstViewController.m
#import "FirstViewController.h"
#import "AppDelegate.h"
#import "SecondViewController.h"
#implementation FirstViewController
#synthesize .....
.............
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.firstField.text = selectedRow;
}
-(IBAction)showTable:(id)sender
{
SecondViewController *controllerSecond = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:controllerSecond animated:YES];
}
SecondViewController.h
#class FirstViewController;
#interface ListaViewController : UIViewController
<UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate>
{
UITableView *table;
UISearchBar *search;
FirstViewController *controller;
}
#property (nonatomic, retain) FirstViewController *controller;
SeconViewController.m
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *selectedRow = [tableData objectAtIndex:indexPath.row];
controller.selectedRow = selectedRow;
[self.navigationController popViewControllerAnimated:YES];
}
Based on your code above, you never set the connection in secondViewController back to first
You probably need something like this:
-(IBAction)showTable:(id)sender
{
SecondViewController *controllerSecond = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[controllerSecond setController:self]; //this sets the reference back
[self.navigationController pushViewController:controllerSecond animated:YES];
}
What you need to use is delegate. It is very commonly used pattern in Object-C. Check out my answer to this SO post. Let me know if you still need code after.
I'm not certain I fully understand what you mean, but why don't you creating an NSString containing the value you need in the SecondViewController. That way you can do something like this when you set up the SecondViewController.
SecondViewController *nextView = [[SecondViewController alloc] init];
nextView.myNSString = #"Value you need in the next view";
Then in SecondViewController.h you'll be able to access the NSString like so:
#NSLog(#"%#", self.myNSString);
The main thing you are missing is the Value passing between views. You are not using any object in any of the view that is passing the value to another view. Like, If you want to pass a text from FirstViewController to SecondViewController. You Can do it as follwos.
NSString *textToPass = self.firstField.text;
In Your SecondViewController there need to be a string object say passedText. When you create object of secondViewController in firstViewController, Do it as follows:
SecondViewController *controllerSecond = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
controllerSecond.passedText = textToPass;
[self.navigationController pushViewController:controllerSecond animated:YES];
Now Wherever you want to show the text of first screen, just use "passedtext" String.
Hope it Helps.
:)
===============================================
In your code you may try the followinf modification:
NSString *selectedRow = [tableData objectAtIndex:indexPath.row];
controller = (FirstViewController *)[self.navigationController topViewController];
controller.selectedRow = selectedRow;
[self.navigationController popViewControllerAnimated:YES];
It Will resolve your problem forsure.
i have 2 views
i m sending text in a button on 1st view to label on second view....
//////textfieldtolabelViewController.h
#import <UIKit/UIKit.h>
#import "seconview.h"
#interface textfieldtolabelViewController : UIViewController {
IBOutlet seconview *sec;
//IBOutlet UITextField *t1;
}
//#property(nonatomic, retain)IBOutlet UITextField *t1;
-(void)buttonclick:(id)sender;
#end
and its .m file is this
#import "textfieldtolabelViewController.h"
#implementation textfieldtolabelViewController
-(void)buttonclick:(id)sender
{
NSString *s = [sender titleForState:UIControlStateNormal];
//sec.ss = s;
[sec settext:s];
[self presentModalViewController:sec animated:YES];
}
- (void)dealloc {
[super dealloc];
}
#end
now there is second view naming seconview
.h file
#import <UIKit/UIKit.h>
#interface seconview : UIViewController {
IBOutlet UILabel *l1;
}
#property(nonatomic, retain)IBOutlet UILabel *l1;
-(void)settext:(NSString *)ss;
#end
and its .m file is ....
#import "seconview.h"
#implementation seconview
#synthesize l1;
//#synthesize ss;
-(void)settext:(NSString *)ss
{
l1.text=ss;
}
- (void)dealloc {
[super dealloc];
}
#end
this program did not show any error and runs fine but problem is that the text of button in 1st view does not appear in label on second view
but i made all connection perfectly.......
Most probably you didn't connect l1 to the actual label in the Interface Builder. Verify with the debugger, that l1 is not nil in your settext method
You can include the view controller containing the label in the view controller where you want it to change, and access it by allocating a copy of it.
For example, use something like this in textfieldtolabelViewController.m
#import "seconview.h"
-(void)buttonclick:(id)sender
{
NSString *s = [sender titleForState:UIControlStateNormal];
seconview *viewcontroller = [[seconview alloc] initWithNibName:#"seconview" bundle:nil];
[[viewcontroller l1] setText:s];
[viewcontroller release];
[self presentModalViewController:sec animated:YES];
}
the [self presentModalViewController:sec animated:YES]; should be above the setText
try it
-(void)buttonclick:(id)sender
{
NSString *s = [sender titleForState:UIControlStateNormal];
//sec.ss = s;
[self presentModalViewController:sec animated:YES];
[sec settext:s];
}
hope it will work....