I'm writing a program for fun, and in it I have a UIViewController with four buttons, they all send the user to another view, but depending on what button is pressed, I want the label in that other view to have a different text. To do that, I decided to have the label's text to be set equals to a NSString variable, and that variable is set to a certain text depending on what button is pressed. So I have this:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"resultScreen"];
[self presentViewController:vc animated:YES completion:nil];
_myLabel.text = [NSString stringWithFormat:myText];
In which myText is the NSString variable I want the label to be set to.
Everything seems to be in order, but the label won't have it's text changed. If I try to change it's text inside the viewDidLoad function, though, it works just fine, so I don't know what is happening.
Any idea of what I might need? If you need more info, just comment what you want and I will try to provide it.
You cannot update UI of other controller from current one - you can set variables and later on in viewDidLoad or viewWillAppear you can assign those values to UI
In File: FirstViewController.m
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SecondViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc.passedText = #"Hello Next";
[self.navigationController pushViewController:vc animated:YES];
In File: SecondViewController.h
#interface SecondViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *myLabel;
#property (strong, nonatomic) NSString *passedText;
In File: SecondViewController.m
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
self.myLabel.text = self.passedText;
}
I think you need to set your ViewController's property before calling the:
[self presentViewController:vc animated:YES completion:nil];
If you set it after presenting the view, you have to manually refresh the view, which is a bit of an overkill. Just set it before presenting the view. So it would look like:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ResultScreenViewController *vc = (ResultScreenViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"resultScreen"];
vc.customTitleLabel.text = [NSString stringWithFormat:myText];
[self presentViewController:vc animated:YES completion:nil];
In your ViewController header file:
#property (nonatomic, strong) UILabel *customTitleLabel;
First Create a subclass of a UIViewController with a custom label:
#interface NextViewController : UIViewController
#property (nonatomic, strong) UILabel* customLabel
#end
Now back to your code. You simple cast the UIViewController you get to the subclass you created so you can access the label inside you view controller.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
NextViewController* nextVC = (NextViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:#"resultScreen"];
nextVC.customLabel.text = [NSString stringWithFormat:myText];
[self presentViewController:nextVC animated:YES completion:nil];
Ok, with the help of one of the answers here I found I solution that works for me. Before, when I had
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"resultScreen"];
[self presentViewController:vc animated:YES completion:nil];
_myLabel.text = [NSString stringWithFormat:myText];
I didn't realise that the resultScreen wasn't linked to UIViewController, but to ViewContronller. So all I needed to do was change the vc declaration to
ViewController *vc = (ViewController *)[mainStoryboard instatiateViewControllerWithIdentifier:#"resultScreen:];
So then all I needed to do was change the label's text at the ViewDidLoad module. It works just fine for me now.
Its simple..
if ([_mylabel.text isEqualToString: myText)
{
//--- Now process your method here. Show alert or what else you need
}
try this. I think that accessing UIlabel directly of other UIViewController is not a good approach. Follow this & it will definitely work.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
resultScreen *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"resultScreen"];
vc.strText = myText;
[self presentViewController:vc animated:YES completion:nil];
In your resultScreen view controller create a NSString property.
resultScreen.h
#property (retain, nonatomic) NSString *strText;
resultScreen.m
-(void)viewDidLoad
{
self.myLabel.text = self.strText;
}
you are trying to set the labelText before presenting the second View.
Before view gets loaded into the memory, its all outlets are nil.
so use the NSString variable in second view, and try to set the value of that variable,and then in
viewWillAppear: method assign the value of string variable to the labelText, this will definitely work.
Cheers!
Related
I'm using delegation to try to change the text from a UILabel in ViewController2.
In ViewController1.h I have:
#protocol WelcomeDelegate
-(void) updateLabelWithString:(NSString*)string;
#end
#interface ViewController1 : UIViewController
#property (weak, nonatomic) id<WelcomeDelegate>delegate;
Inside ViewController1.m:
- (void)presentWelcomeAlert {
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewController2* contentVC = [storyboard instantiateViewControllerWithIdentifier:#"ViewController2ID"];
[self.delegate updateLabelWithString:[NSString stringWithFormat:#"Welcome to the 11Health Family %#! We are here to accompany and support you through the journey as an ostomate. Our new Hydration Tracker is ready to follow your hydration levels. Tap 'Continue' to begin!", [dcsContext sharedContext].activeParticipant.firstName]];
UIViewController *rootVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
[rootVC presentViewController:contentVC animated:YES completion:nil];
}
Inside ViewController2.h I have:
#import "SignInViewController.h"
#interface WelcomePopoverViewController () <UIViewControllerTransitioningDelegate>
{
SignInViewController *signInViewController;
}
In the viewDidLoad:
viewController1 = [[ViewController1 alloc] init];
[viewController1 setDelegate:self];
My method in ViewController2.m:
- (void)updateLabelWithString:(NSString *)string {
welcomeLabel.text = string;
}
My issue is that the method above isn't getting called even when I call it from the first view controller.
This is a bit messy, sorry to say.....and you are re-instantiating ViewController1 in ViewController2....
If you only need to set that label once, then ditch all the delegate/protocol stuff and just call the method directly:
- (void)presentWelcomeAlert {
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewController2* contentVC = [storyboard instantiateViewControllerWithIdentifier:#"ViewController2ID"];
UIViewController *rootVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
[rootVC presentViewController:contentVC animated:YES completion:^ {
[contentVC updateLabelWithString:[NSString stringWithFormat:#"Welcome to the 11Health Family %#! We are here to accompany and support you through the journey as an ostomate. Our new Hydration Tracker is ready to follow your hydration levels. Tap 'Continue' to begin!", [dcsContext sharedContext].activeParticipant.firstName]];
}];
}
and then of cause expose that method in ViewController2.h:
-(void) updateLabelWithString:(NSString*)string;
You can directly call this method no need to create delegate.
ViewController2 *obj=[[ViewController2 alloc] init];
[obj updateLabelWithString:#"title"];
[self.navigationController pushViewController:obj animated:YES];
My first view in the viewDidLoad has the following code
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Dialpad" bundle:nil];
self.vc = [sb instantiateViewControllerWithIdentifier:#"DialpadBoard"];
self.vc.delegate = self;
The header file contains the definition of the view controller
#property (nonatomic, retain) DialpadTableViewController *vc;
after catching an event the view loads a new modal view
- (void)handleEvent:(UIGestureRecognizer*)recognizer {
[self presentViewController:self.vc animated:YES completion:NULL];
}
The view also contains the method to dismiss the modal view:
- (void) dialpadControllerDidCancel:(SearchDialpadTableViewController *)controller {
[self dismissViewControllerAnimated:YES completion:nil];
}
The last method never gets called.
The problem is that the modal view when it is loaded has nil self.delegate. The new modal view is loaded from the storyboard as seen below. Why the delegate is nil? I cannot how a segue since the view is in another storyboard.
you can try this
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Dialpad" bundle:nil];
UINavigationController *nav= [sb instantiateViewControllerWithIdentifier:#"DialpadBoard"];
((SearchDialpadTableViewController *)[nav viewControllers][0]).delegate = self;
[self presentViewController:nav animated:YES completion:NULL];
Since we have the nav let's take the first controller and assign the delegate
the trick ;)
((SearchDialpadTableViewController *)[nav viewControllers][0]).delegate = self;
Does SearchDialpadTableViewController define a delegate protocol and does it have a property that is specific to that protocol?
The header for that file should look something like:
#protocol ViewControllerDelegateProtocol <NSObject>
- (void)dialpadControllerDidCancel:(SearchDialpadTableViewController *)controller;
#end
#interface ViewController : UIViewController
#property (weak, nonatomic) id<ViewControllerDelegateProtocol> searchPadDelegate;
#end
Then when the user taps Done which is I'm assuming what you're trying to do (send a delegate message when that happens). You would write something like
- (IBAction)donePressed:(id)sender
{
if ([self.searchPadDelegate respondsToSelector:#selector(dialpadControllerDidCancel)]) {
[self.searchPadDelegate dialpadControllerDidCancel:self];
}
}
you must be certain, that self.vc is a class, that you expected. It can be also NavigationController
Helo all,
I am moving from one view controller to another using below code.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"RoloBusinessCard"];
[self.navigationController pushViewController:vc animated:YES];
Now i want to pass some data from one view controller to another like some variable.I have got this code to do this task but i am not making instance of another view controller.I am starting another view controller using storyboard.
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.str1 = str;
[self.navigationController pushViewController:secondViewController animated:YES];
Please tell me how can i pass data between view controllers in my way?
Solution does not work
decalre NSString in .h file.
#property (nonatomic, strong) NSString *UserId;
Synthesize in .m file
#synthesize UserId;
Code for navigation
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"RoloBusinessCard"];
vc.UserId=#"abc";
[self.navigationController pushViewController:vc animated:YES];
But vc.UserId does not recognized.
You can pass data between two ViewControler with the help of properties.
First in RoloBusinessCard.h ViewControler make a property like this
#property (nonatomic, strong) NSString *str1;
in .m file of this class synthesize it like this
#synthesize str2;
Now like this you can pass value
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"RoloBusinessCard"];
vc.str2=str2
[self.navigationController pushViewController:vc animated:YES];
If you are not able to get str2 in RoloBusinessCard
First Replace UIViewController with Your Viewcontroller Name like this
RoloBusinessCard *vc = [storyboard instantiateViewControllerWithIdentifier:#"RoloBusinessCard"];
or
typecase UIViewController like this
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"RoloBusinessCard"];
(RoloBusinessCard *)vc1=vc
vc1.str2=str2
[self.navigationController pushViewController:vc1 animated:YES];
Hope it help.
Try Like this, Hope it will work.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
SecondViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"RoloBusinessCard"];
vc.str1 = str;
[self.navigationController pushViewController:vc animated:YES];
Here we are just using Navigation stack for passing data to the next controller
create a property in 2nd view controller
#property (nonatomic, strong) NSString *yourString;
in firstView controller action method
object of view controller which you will create on push method do
-(void)btnAtion{
object.yourstring = txtyourfirstvcObject.text
}
In swift, we can do the same
let's suppose we want to pass a Bool Value to the next controller so we can do :
Class ToViewController : UIViewController {
public var isSelected : Bool?
}
Class FromViewController : UIViewController {
#IBAction func onClickFlyingFrom(_ sender: UIButton) {
let tvc = self.storyboard?.instantiateViewController(withIdentifier: "ToViewController") as! ToViewController
tvc.isSelected = true
self.navigationController?.present(vc, animated: true, completion: nil)
}
}
I have a problem with the implementation of FPPopover library.
I have a similar issue than on an other post : Same issue on StackOverFlow
Unfortunately, a reference to the popover controller does not fix my problem.
On my future controller, I have an UITableView dynamically loaded when the action button is clicked. This is my code:
- (IBAction)displayAlternateNicknames:(id)sender{
PXAlternativeNicknamesViewController * suggestionsVC= [[UIStoryboard storyboardWithName:[ViewsParamsSingleton sharedLoginSignUpStoryBoard] bundle:nil] instantiateViewControllerWithIdentifier:NicknameSuggestionsStoryBoardID];
suggestionsVC.title=#"Suggestions";
suggestionsVC.nicknameSuggestions=self.nicknameSuggestions;
suggestionsVC.callerVC=self;
//our popover
suggestionsPopover = [[FPPopoverController alloc] initWithViewController:suggestionsVC];
suggestionsPopover.contentSize = CGSizeMake(200,200);
//the popover will be presented from the okButton view
[suggestionsPopover presentPopoverFromView:sender];
}
Here's my implementation that's working in production. Try this out. It may just be that you haven't set all the properties correctly.
// MyViewController.m
#interface MyViewController ()
#property(nonatomic, strong) FPPopoverController *popover;
#end
...
// Instantiate popover
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
LoginViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
if (self.popover) {
[self.popover dismissPopoverAnimated:NO];
self.popover = nil;
}
self.popover = [[FPPopoverController alloc] initWithViewController:viewController];
self.popover.contentSize = viewController.size;
self.popover.border = NO;
self.popover.arrowDirection = FPPopoverNoArrow;
self.popover.tint = FPPopoverRedTint;
[self.popover presentPopoverFromView:self.loginButton];
If the problem persists, I found another answer here that might help. Essentially, you'd have to disable ARC for FPPopover. I'm not sure how to do this with Cocoapods so you may have to just copy-and-paste the library directly into your project instead. I know it's not an ideal solution, but I think it's worth a shot.
Yet another possibility is to create an instance variable of your FPPopover and reference it that way. Example:
#property (nonatomic, strong) FPPopover *popover;
...
- (FPPopover *)popover {
if(!_popover){
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
LoginViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
_popover.contentSize = viewController.size;
_popover.border = NO;
_popover.arrowDirection = FPPopoverNoArrow;
_popover.tint = FPPopoverRedTint;
}
return _popover;
}
...
-(void)buttonTapped:(UIButton *)sender{
[self.popover presentPopoverFromView:sender];
}
I've got a view in a xib file that I load to my viewController - its a temp view and thus isn't on screen all the time. However the temp view and the main view, use the same view controller class as they both are doing the same job.
Now, in the xib view I load up a second viewControoler - lets call it viewControllerB - which is a UITableView with 197 cells. Once a cell is selected, the view is dismissed and the value of the cell is returned to viewControllerA.
viewControllerB is on the storyboard.
Here is the code I have used:
viewControllerB (The VC I need data back from)
Delegate Protocol:
#protocol CountrySelectedDelegate <NSObject>
-(void)selectedCountry: (id)countryReturned;
#end
#property (strong, nonatomic) id <CountrySelectedDelegate> myDelegate;
Then in the .m file:
Set the delegate:
ViewControllerA *viewA = [[ViewControllerA alloc]init];
self.myDelegate = viewA;
Then I call the delegate in the same file;
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[self myDelegate] selectedCountry:indexPath.row];
[self dismissViewControllerAnimated:YES completion:nil];
}
Now in viewControllerA:
pragma mark - CountrySelected Delegate
-(void)selectedCountry:(id)countryReturned
{
self.testInt = countryReturned;
}
Now this method does get called by the delegate. Looking in the console: countryReturned is the correct value. Once this method has finished, self.testInt is also the correct value.
Then, in my viewWillAppear method, I simply check the value again to see if its still the same with a NSLog print.
the value is always nil in the viewWillAppear method (Or anywhere else I check it) - I have tried with NSMutableString and NSString - always nil.
Why are my properties / instance variables getting set to nil?
Update:
This is how I show viewControllerB
- (IBAction)countrySelect:(UIButton *)sender
{
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
UITableViewController *vc = [sb instantiateViewControllerWithIdentifier:#"CountrySelection"];
vc.modalTransitionStyle = UINavigationControllerOperationPop;
[self presentViewController:vc animated:YES completion:NULL];
}
On ViewB do the below I guess you have already done
#protocol CountrySelectedDelegate <NSObject>
-(void)selectedCountry: (NSInteger)countryReturned;
#end
#property (week, nonatomic) id <CountrySelectedDelegate> myDelegate;
and in didSelectRowAtIndexPath
if ([[self myDelegate] respondsToSelector:#selector(selectedCountry:)])
{
[[self myDelegate] selectedCountry:indexPath.row];
}
On ViewA
Conform the protocol
#interface ViewA : UIViewController < CountrySelectedDelegate >
create the call ViewB
ViewB *viewBObjc=[[ViewB alloc] init];
[viewBObjc setMyDelegate:self];
[[self navigationController] presentViewController:ViewB animated:YES completion:Nil];
implement the delegate on ViewA
-(void)selectedCountry: (NSInteger)countryReturned
{
NSLog(#"Country Id is :%d", countryReturned);
}
Try this,
Set delegate by
//in ViewControllerB
self.myDelegate = [self parentViewController];
or
- (IBAction)countrySelect:(UIButton *)sender
{
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
ViewControllerB *vc = (ViewControllerB *)[sb instantiateViewControllerWithIdentifier:#"CountrySelection"];
vc.modalTransitionStyle = UINavigationControllerOperationPop;
vc. myDelegate = self;
[self presentViewController:vc animated:YES completion:NULL];
}