I defined a UITextField on my firstViewController as follow
// firstViewController.h
IBOutlet UITextField *PickUpAddress
#property (nonatomic, retain) UITextField *PickUpAddress;
//firstViewController.m
#synthesize PickUpAddress;
// Push secondView when the 'Done' keyboard button is pressed
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
if (textField == PickUpAddress) {
SecondViewController *secondViewController= [[SecondViewController alloc]
initWithNibName:#"SecondViewController"
bundle:nil];
secondViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:secondViewController animated:YES];
[secondViewController release];
}
return NO;
}
Then I tried to retrive it in my secondViewController during viewWillAppear
- (void)viewWillAppear:(BOOL)animated {
BookingViewController *bookingViewController = [[BookingViewController alloc] init];
NSString *addressString = [[NSString alloc] init];
addressString = bookingViewController.PickUpAddress.text;
NSLog(#"addressString is %#", bookingViewController.PickUpAddress.text);
}
But it returns as NULL on my console. Why is that so?
Thanks in advance :)
in secondViewController.h add
NSString *text;
#property (nonatomic, retain) NSString *text;
-(void)setTextFromText:(NSString *)fromText;
in secondViewController.m add following
- (void)setTextFromText:(NSString *)fromText
{
[text release];
[fromText retain];
text = fromText;
}
in firstViewController.m
before
[self.navigationController pushViewController:secondViewController animated:YES];
add
[secondViewContoller setTextFromText:PickUpAddress.text];
Now let me explain the code.
You are adding an NSString to second view , where we will store the text from the UITextField. Then, we've written a method, which will set that NSString from some other NSString.
Before pushing secondViewController to navigationController, you're just calling that method to set our text from PickUpAddress.text.
Hope that helped.
Problem is in your code. You are creating new object, bookingViewController, to retrieve the textField value. So it will obviously provide NULL. Rather you should use one unique object application wide to access the value.
Related
I have 2 classes with xib files (not in storyboard). when i pass a value from one class to another it always worked before Xcode 5. But now its not working on Xcode 5. I am passing the value from TimeZoneViewController to SignUpViewController as following:
NSLog(#"value: %#",cell.textLabel.text);
SignUpViewController *signUp = [[SignUpViewController alloc]initWithNibName:#"SignUpViewController" bundle:nil];
[signUp.timeZoneLabel setText:cell.textLabel.text];
[self.navigationController pushViewController:signUp animated:YES];
The log is showing the value but after SignUpViewController appears it shows nothing in the "timeZoneLabel". Where is the problem? Thanks in advance.
Your code will navigate you to next screen before setting the value of timeZoneLabel. So, you should swap your 3rd line with 4th one to set the text of timeZoneLabel first and then to navigate to the SignUpViewController.
Use this Code :
NSLog(#"value: %#",cell.textLabel.text);
SignUpViewController *signUp = [[SignUpViewController alloc]initWithNibName:#"SignUpViewController" bundle:nil];
[signUp.timeZoneLabel setText:cell.textLabel.text];
[self.navigationController pushViewController:signUp animated:YES];
Update :
1) Create a property in SignUpViewController
#property (strong, nonatomic) NSString * strTimeZoneLabel;
2) In first view controller, set that property value.
NSLog(#"value: %#",cell.textLabel.text);
SignUpViewController *signUp = [[SignUpViewController alloc]initWithNibName:#"SignUpViewController" bundle:nil];
signUp.strTimeZoneLabel = cell.textLabel.text;
[self.navigationController pushViewController:signUp animated:YES];
3) In -viewDidLoad of SignUpViewController, set the text of timeZoneLabel :
self.timeZoneLabel.text = self.strTimeZoneLabel;
SignUpViewController's view is not loaded to memory from xib, so signUp.timeZoneLabel == nil. Use controller property to send value:
signUp.timeZoneLabelText = cell.textLabel.text;
Here is your property:
#property (strong, nonatomic) NSString * timeZoneLabelText;
And here is implementation method:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.timeZoneLabel setText:self.timeZoneLabelText];
}
Change your code adding a NSString and update like this :
OtherView.h
#property (nonatomic, strong) NSString *myText;
OtherView.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.timeZoneLabel setText:self.myText];
}
Pass data :
NSLog(#"value: %#",cell.textLabel.text);
SignUpViewController *signUp = [[SignUpViewController alloc]initWithNibName:#"SignUpViewController" bundle:nil];
[signUp.myText setText:cell.textLabel.text];
[self.navigationController pushViewController:signUp animated:YES];
You can not set the label text of another view controller so you have to pass string value from one class to another class and assign this string value to label in signupviewcontroller's viewDidLoad method.
Like Below Code
In SignUpViewController.h File
#property (nonautomic, retain) NSString *strTimeZone;
#property (nonautomic, retain) UILabel *lblTimeZone;
In SignUpViewController.m File
- (void)viewDidLoad
{
[super viewDidLoad];
self.lblTimeZone.text = strTimeZone;
}
In firstviewcontroller File from where you want to push another class
NSLog(#"value: %#",cell.textLabel.text);
SignUpViewController *signUp = [[SignUpViewController alloc]initWithNibName:#"SignUpViewController" bundle:nil];
signUp.strTimeZone = cell.textLabel.text;
[self.navigationController pushViewController:signUp animated:YES];
try like this your problem will solved
I have a view controller and a class (I am using storyboards). How can I change the text of a UILabel (in the view controller) from the class? I have tried this, but to no avail:
ViewController *mainView = [[ViewController alloc] init];
[mainView view];
[mainView.progressBar setProgress:integer animated:YES];
NSLog(#"Updated Progress Bar");
NSString *progressLabelText = [NSString stringWithFormat:#"%# out of %i followers", userString, [self.followers count]];
[mainView.progressLabel setText:progressLabelText];
NSLog(#"Updated Progress Label Text: %#", progressLabelText);
The text does not change using this code. What should I be doing instead?
Edit: The progressbar and label in the ViewController's .h file look like this:
#property (nonatomic, strong) IBOutlet UIProgressView *progressBar;
#property (nonatomic, strong) IBOutlet UILabel *progressLabel;
And they are fully linked up in Interface Builder.
Use delegate for messaging between classes or viewcontrollers.
Refer The Basics of Protocols and Delegates link.
Try to use Notification for updating the Lable text.
in your viewController write this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateLabel) name:#"lblUpdate" object:nil];
and selector is :
-(void)updateLabel
{
self.lblObject.text = #"Your updated text"
}
and now in your Class call this using Post notification:
[[NSNotificationCenter defaultCenter] postNotificationName:#"lblUpdate" object:nil];
remember use same notification name "lblUpdate"
just property synthesize the string and then set that string in viewWillAppear: method of ViewController.m class
just take NSString variable in ViewController.h file like bellow..
#property (nonatomic, retain) NSString *progressText;
and synthesize this in ViewController.m file like bellow..
#synthesize progressText;
after that in viewDidLoad: method just set text at starting to the progressLableText like bellow...
- (void)viewDidLoad
{
progressText = #"Your Text";
[progressLabel setText:progressText];
}
and also in viewWillAppear: set the text like above...
- (void)viewWillAppear:(BOOL)animated
{
[progressLabel setText:progressText];
}
and in your code just change something like bellow..
ViewController *mainView = [[ViewController alloc] init];
[mainView view];
[mainView.progressBar setProgress:integer animated:YES];
NSLog(#"Updated Progress Bar");
NSString *progressLabelText = [NSString stringWithFormat:#"%# out of %i followers", userString, [self.followers count]];
mainView.progressText = progressLabelText;
[mainView.progressText retain];
NSLog(#"Updated Progress Label Text: %#", progressLabelText);
i hope this helpful to you...
But use a delegate to do the callbacks.
In your spamchecker.h add:
#protocol SpamCheckerDelegate <NSObject>
-(void)updateText:(NSString*)newText;
#end
#property (nonatomic, weak) id <SpamCheckerDelegate> delegate;
In your spamchecker.m where you need it add:
[self.delegate updateText:#"newText"];
Then in your mainView.h add:
#interface MainView : UIViewController <SpamCheckerDelegate>
In your mainview.m add:
spamchecker.delegate = self;
And implement the method like:
-(void)updateText:(NSString*)newText
{
[self.progressLabel setText:progressLabelText];
}
I have a sequence of 4 viewControllers inside a NavigationController, each grabs a few textFields of input from the user which are stored in a NSMutableDictionary.
Each of the VC's set's itself up as the delegate of the nextVC before it segues, it also passes the NSMutDict along.
This works fine.
What I don't understand is this:
Say I have filled in the 5 textFields in VC1. Then I set myself as the delegate of VC2, pass VC2 the dictionary with the input data and segue to VC2. In VC2 I fill in another 4 textFields and add these to the dictionary. If I then decide I need to change something in VC1 I tap the back button and amend the data. But when I go forwards again I lose the stuff I input on VC2.
How do I pass the dictionary back to VC1 with the added info so that when it gets passed forwards to VC2 again it has everything in it?
The delegate (VC1) has a method to update its dictionary with the dictionary in VC2.
I have also customised the backBarButtonItem in VC2 by setting it in the prepareForSegue: method in VC1.
I think I'm getting close but...
I can only get the target actions to work by setting a leftBarButtonItem in VC2 and using that instead of the default back button.
Setting the back button in VC1 (prepareForSegue:) doesn't seem to allow any target or action to be set.
I know I can't set the back button in VC2, so what can I do? Can I set the target and action of the back button from VC2 using the delegate?
I think it may be something to do with UINavigationBarDelegate but I can't figure out where to put what with that. I tried setting it up in VC2 but it didn't do anything.
TIA.
Here's the relevant code:
Protocol:
#import <Foundation/Foundation.h>
#protocol IAXAddNewUserDelegate <NSObject>
#required
- (void)updateNewUserDataWithData: (NSMutableDictionary *)newData;
#end
From VC1.h:
#import "IAXAddNewUserDelegate.h"
#interface IAXAddNewUser1 : UITableViewController <UITextFieldDelegate, UIAlertViewDelegate, IAXAddNewUserDelegate>
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (strong, nonatomic) User *selectedUser;
#property (strong, nonatomic) User *aNewUser;
#property BOOL isFirstUser;
- (void)updateNewUserDataWithData: (NSMutableDictionary *)newData;
#end
From VC1.m:
#pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"AddUser2"]) {
IAXAddNewUser2 *addUser2VC = segue.destinationViewController;
addUser2VC.managedObjectContext = self.managedObjectContext;
addUser2VC.progressTotal = self.progressTotal;
addUser2VC.isFirstUser = self.isFirstUser;
addUser2VC.userData = self.userData;
addUser2VC.delegate = self;
if (self.selectedUser) {
addUser2VC.selectedUser = self.selectedUser;
}
self.title = #"Step 1";
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(passDataBack:)];
self.navigationItem.backBarButtonItem = backButton;
}
}
#pragma mark - IAXAddNewUserDelegate Methods
- (void)updateNewUserDataWithData: (NSMutableDictionary *)newData
{
self.userData = newData;
NSLog(#"Updated AddUserVC1");
}
From VC2.m
-(void)passDataBack:(id)sender
{
NSLog(#"Sending Data Back to VC1");
[self.delegate updateNewUserDataWithData:self.userData];
[self.navigationController popViewControllerAnimated:YES];
}
If you're updating all the dictionaries from all the other dictionaries, try using a singleton. You can see an example here: https://stackoverflow.com/a/9690731/542400
Also, here's some code:
MainDictionary.h
#interface MainDictionary : NSObject{
NSMutableDictionary *dictionary;
}
+(MainDictionary *)sharedDictionary;
-(NSString *)getStringForKey:(NSString *)string;
-(void)setString:(NSString *)string forKey:(NSString *)key;
#end
MainDictionary.m
#import "MainDictionary.h"
static MainDictionary *sharedDictionary;
#implementation MainDictionary
-(id)init{
self = [super init];
dictionary = [[NSMutableDictionary alloc] init];
// if you want to add anything preliminary to the dictionary, do it here
return self;
}
+(MainDictionary *)sharedDictionary{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedDictionary = [[self alloc] init];
});
return sharedDictionary;
}
-(NSString *)getStringForKey:(NSString *)string{
return [dictionary objectForKey:string];
}
-(void)setString:(NSString *)string forKey:(NSString *)key{
[dictionary setValue:string forKey:key];
}
#end
Now #import MainDictionary.h, and any time you want to access or set values in that dictionary (in this example, when your textFields end editing), just do this:
-(void)textFieldDidEndEditing:(UITextField *)textField{
if(textField == textField1){
[[MainDictionary sharedDictionary] setString: textField.text forKey:#"textField1"];
}
}
or:
-(void)viewWillAppear{
textField1.text = [[MainDictionary sharedDictionary] getStringForKey:#"textField1"];
[super viewWillAppear:YES];
}
Implement this in each VC, and you're good to go.
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.
hi i am new to iphone development.
I'm trying with sample where I need to copy a string from the textfield of viewController and display it on the next view with a Label.
On the first view there is button bellow the textfield.1
I am not able to fix some issues showing BAD ACESS can anyone help me in solving this.
Let me know what i'm doing Wrong.
Thank you.
//copystring.h
#interface CopystringViewController : UIViewController{
UITextField *myTextField;
NSString *somestring;
}
#property(nonatomic,retain)IBOutlet UITextField *myTextfield;
#property(nonatomic,retain)NSString *somestring;
-(IBAction)next:(id)sender;
//.m file
#synthesize myTextfield,somestring;
-(IBAction)next:(id)sender;
{
NextView * next = [[NextView alloc] initWithNewString: myTextField.text];
[self.navigationController presentModalViewController: next animated: YES];
}
NextView.h
#interface NextView : UIViewController{
UILabel *string2;
}
#property(nonatomic,retain)IBOutlet UILabel *string2;
- (id)initWithNewString:(NSString*)someString;
//.m file
#synthesize string2;
-(id)initWithNewString:(NSString*)someString {
string2 = someString;
return self;
}
Just replace method.it may run.
-(IBAction)next:(id)sender; {
NextView * next = [[NextView alloc] initWithNibName:#"NextView" bundle:nil];
next.string2=myTextField.text;
[self.navigationController presentModalViewController:next animated: YES];
}
hey string2 is a label so try string2.text = somestring;
-(id)initWithNewString:(NSString*)someString {
string2.text = someString;
return self;
}
It looks like the problem is that you're assigning an NSString (someString) to a UILabel (string2).
AppleVijay's answer should do the trick.
If you don't like dot-notation in ObjC you can also write it like this:
[string2 setText:someString]
U can declare ur somestring in to the delagate h/m file that way it wil be the global string. u can use it with appdaligateobj.stringname.
U dont evn need init u can directly add to viewdidload of next view.
string2.text = AppDalegateobj.stringName.
Delegation is the usual way to move data around like this. I wrote a very simple example project to show this in action.
You need init you view and retain you string:
-(id)initWithNewString:(NSString*)someString {
self = [super init];
if (self) {
string2.text = someString;
}
return self;
}
/
/AppDelegate.h
NSString *String1;
#property (nonatomic, retain) NSString * String1;
//AppDelegate.m
#synthesize String1
//ViewController1.h
AppDelegate * objAppDelegate;
UILable *lblstring;
#property (nonatomic, retain) UILable *lblstring;
//ViewController1.m
#synthesize lblstring
//On View Did Load.
objAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
lblstring.text = objAppDelegate.String1;