I am trying to pass NSString value to another ViewController. But I get null instead of the value. Here is my code.
FirstViewController.m:
NSString cellID = #"66";
SecondViewController *apiViewController = [[SecondViewController alloc] init];
apiViewController.strMessage=cellID;
[self.navigationController pushViewController:apiViewController animated:YES];
SecondViewController.h:
#interface SecondViewController : UIViewController{
NSString *strMessage;
}
#property(nonatomic,retain) NSString *strMessage;
#end
SecondViewController.m:
#implementation SecondViewController
#synthesize strMessage;
NSLog(#"%#", strMessage);
#end
I did import. I assigned variable before pushing. But it anyway returns null. How can I do this? Any tips, ideas. Thank you.
Try assigning the property before you push the view controller.
NSString cellID = #"66";
LineChartViewController *apiViewController = [[LineChartViewController alloc] init];
apiViewController.strMessage=cellID;
[self.navigationController pushViewController:apiViewController animated:YES];
Furthermore, you need to call the NSLog from within a function in your implementation. The viewDidLoad function, for example, as this is a UIViewController that is being pushed on a UINavigationController stack.
try this code
SecondViewController *apiViewController = [[SecondViewController alloc] init];
apiViewController.strMessage=cellID;
[self.navigationController pushViewController:apiViewController animated:YES];
Try this
SecondViewController *apiViewController = [[SecondViewController alloc] init];
apiViewController.strMessage=cellID;
[self.navigationController pushViewController:apiViewController animated:YES];
And Print
NSLog(#"%#", self.strMessage);
Related
The select item is a slider. When I click the slider It will pass the data to Second VC (WebViewController). but how to pass data from first view controller to second view controller in objective-c? Sorry, This is my first time coding objective C.
First VC .m file
#import "WebViewController.h"
- (void)viewDidLoad {
[super viewDidLoad];
arraySliderProducts = [[NSMutableArray alloc]init];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
UIViewController *controller = nil;
switch (indexPath.row)
{
case 0:
{
WebViewController *WebViewController = [[WebViewController alloc] init];
//error: No visible #interface for "WebViewController" declares the selector 'alloc'
WebViewController.data = arraySliderProducts[indexPath.row][#"title"]; //pass this link value
//error: Property 'data' not found on object of type 'WebViewController'
[self.navigationController pushViewController: WebViewController animated:YES];
}..
Second VC .m file
#interface WebViewController ()
#property (nonatomic, retain) NSString *data;
Second VC .h file
#import <UIKit/UIKit.h>
#interface WebViewController : UIViewController
{
AppDelegate *appDelegate;
NSString *data;
}
#end
Two points to note:
1: This is not the way to initiate a view controller to show/present in your app.
2: You should declare your NSString *data in your SecondVC's .h file.
Now point 1 solutions is to change your code with below in your didSelectItemAtIndexPath: function
switch (indexPath.row)
{
case 0:
{
// By Default storyboard name is "Main". Change it if you you have different name in your project
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
// Now instantiate your view controller with its identifier on this storyboard object.
// Note: don't forget to set viewControllers' identifier
WebViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier: #"WebViewController"];
// Now Pass your value
WebViewController.data = arraySliderProducts[indexPath.row][#"title"];
//Finally push this object on your navigation stack
[self.navigationController pushViewController: WebViewController animated:YES];
}...
}
try as
//Your class and obj name is same so You are getting this type of error
WebViewController *VC = [[WebViewController alloc] init];
//OR
WebViewController *VC= [self.storyboard instantiateViewControllerWithIdentifier:#"WebViewController"];
VC.data = arraySliderProducts[indexPath.row][#"title"];
[self.navigationController pushViewController: VC animated:YES];
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];
Today I use MVC to build a photo album.But I can't get data in ViewControllerB that pass from ViewControllerA,I read this article here is link (Passing Data between View Controllers), and check all the steps I do.
Here is code in ViewControllerA:
PhotoViewController *photoVC = [[PhotoViewController alloc] initWithNibName:nil bundle:nil];
photoVC.images = images;
photoVC.index = index;
photoVC.view.backgroundColor = [UIColor lightGrayColor];
[self presentViewController:photoVC animated:YES completion:^{
// code
}];
Here is code in ViewControllerB:
#interface PhotoViewController : UIViewController
#property (nonatomic ,retain) NSMutableArray *images;
#property (nonatomic, assign) NSInteger index;
#end
here is .m file
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#", self.images);
}
But I got nothing, I don't know where I was wrong, how to make it right?? Thanks a lot.
I don't think you can instantiate your PhotoViewController from:
PhotoViewController *photoVC = [[PhotoViewController alloc] initWithNibName:nil bundle:nil];
Do this instead:
PhotoViewController *photoVC = [[PhotoViewController alloc] init];
Or you should pass the identifier to nibName, otherwise how can it find out which Nib file to load?
EDIT:
You should put this code section inside the animation completion block. UIViewController is not full instantiated when you pass data like you did.
[self presentViewController:photoVC animated:YES completion:^{
photoVC.images = images;
photoVC.index = index;
photoVC.view.backgroundColor = [UIColor lightGrayColor];
}];
EDIT 2:
Reason:
The nib file you specify is not loaded right away. It is loaded the
first time the view controller's view is accessed. If you want to
perform additional initialization after the nib file is loaded,
override the viewDidLoad method and perform your tasks there.
Storyboard equal between two controller and controller runing.
PhotoViewController *photoVC = [[PhotoViewController alloc] initWithNibName:nil bundle:nil];
photoVC.images = images;
photoVC.index = index;
photoVC.view.backgroundColor = [UIColor lightGrayColor];
[self presentViewController:photoVC animated:YES completion:^{
// code
}];
I have a UINavigationController and I'm trying to release from memory every UIViewController once another one is on top of the stack. I assign the viewControllers property of the UINavigationController to the new UIViewController and then pop into it. This way I always have just one UIViewController in stack. However, the memory keeps adding up every time I create a new UIViewController. Dealloc is called, but the memory usage remains the same.
You can download the example project HERE
FirstViewController.h
#import "SecondViewController.h"
#interface FirstViewController : UIViewController
-(IBAction)goToSecond:(id)sender;
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", self.navigationController.viewControllers);
}
-(void)goToSecond:(id)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
[self.navigationController setViewControllers:#[secondVC]];
[self.navigationController popViewControllerAnimated:NO];
}
-(void)dealloc{
NSLog(#"FirstVC dealloc");
}
#end
SecondViewController.h
#import "FirstViewController.h"
#interface SecondViewController : UIViewController
-(IBAction)goToFirst:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", self.navigationController.viewControllers);
}
-(void)goToFirst:(id)sender{
FirstViewController *firstVC = [[FirstViewController alloc]init];
[self.navigationController setViewControllers:#[firstVC]];
[self.navigationController popViewControllerAnimated:NO];
}
-(void)dealloc{
NSLog(#"SecondVC dealloc");
}
#end
Navigation controller should not be used as you intended.
You should call pushViewController and popViewController for present/dismiss your viewControllers.
If you have memory issues, try to release memory in didReceiveMemoryWarning callback
I'm not sure about the benefit of a uinavigationcontroller but anyway you could add this snippet on your .m of your uiviewcontrollers
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
if (self.navigationController.viewControllers.count > 1) {
NSMutableArray *newViewControllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[newViewControllers removeObject:[controllers objectAtIndex:1]];
self.navigationController.viewControllers = newViewControllers;
}
}
And instead of
[self.navigationController setViewControllers:#[firstVC]];
[self.navigationController popViewControllerAnimated:NO];
you can set
[self.navigationController pushViewController:[[FirstViewController alloc] init] animated:NO];
You are using pop to go further, but you need to use push if you want to go to the next ViewController.
-(void)goToSecond:(id)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
[ self.navigationController pushViewController:secondVC animated:YES];
}
And in the SecondViewController to go back to your FirstViewController you should use pop
-(void)backToController
{
[self.navigationController popViewControllerAnimated:YES];
}
In your case
-(void)goToFirst:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
I uploaded a simple app to GitHub, with the fake navigation bar that i was talking about in my comment, hope it helps for your needs: https://github.com/yosihashamen/HelpersApps
Be ware that you must keep on "BaseViewController" alive at all times.
What I mean is something like this.
In your FirstViewController use presentViewController instead of push adding a new UINavigationController to the SecondViewController
-(void)goToSecond:(id)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:secondVC];
[self presentViewController:nav animated:YES completion:NIL];
}
In the SecondViewController add an UIBarButtonItem to the Navigation bar
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleDone target:nil action:#selector(goToFirst:)];
self.navigationItem.backBarButtonItem = backButton;
And implement dismiss method.
-(void)goToFirst:(id)sender
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
Try out setViewControllers:animated:
This allows you to explicitly set the view controllers on the UINavigationController stack, like you are doing, and it will automatically handle the navigation animation without you having to call popViewControllerAnimated:
This is useful if you have a multi-view journey where you need to get rid of the screens that have been shown so far but maintain the navigation animation (eg. app demo on launch) or if you want to easily push multiple view controllers on the navigation stack at once.
Apple doc here: https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html#jumpTo_21
I have a navigation based application.On click of a button on the navigation bar in the first screen , I am able to push another view controller as follows :
-(void) buttonClicked:(id)sender
{
UIViewController* mv = [[SecondViewController alloc] init];
[[self navigationController] pushViewController:mv animated:YES];
}
Now i have a UIView(separate .h and .m files) as part of the first screen. On click of a button in the UIView, i want to push the SecondViewController.
I have tried the following :
UIViewController* mv = [[SecondViewController alloc] init];
UIViewController * home=[[FirstViewController alloc]init];
[[home navigationController] pushViewController:mv animated:YES];
It doesnt work!! Kindly help
UIViewController* mv = [[SecondViewController alloc] init];
UIViewController * home=[[FirstViewController alloc]init];
[[home navigationController] pushViewController:mv animated:YES];
The problem here is that home isn't part of the navigation stack, so [home navigationController] is surely nil. I'm not quite clear on what you're trying to do here, but just creating a view controller doesn't mean that it's actually part of the view controller graph.
Why would it work? Randomly creating view controllers whose view is not even visible, is not the solution. You can either keep a reference to the VC in the view like this:
#imlementation ViewController
- (id) init
{
// ...
aView = [[CustomView alloc] init];
aView.viewController = self;
// ...
}
#end
#interface CustomView
#property (assign) ViewController *viewController;
#end
Or you can search the responder chain at runtime:
UIResponder *next = [view nextResponder];
while (next)
{
if ([next isKindOfClass:[ViewController class]])
{
break;
}
next = [next nextResponder];
}
And now "next" will contain the view controller (or nil if it can't be found).
Try using the same navigationController to push view, this keeps the same stack of ViewControllers.
UIViewController* mv = [[SecondViewController alloc] init];
[[self navigationController] pushViewController:mv animated:YES];
[mv release];
I see your problem now! You need to #import your FirstViewController, then #class it. Then do your push.
So:
//.h
#import "FirstViewContoller.h"
#class FirstViewController;
#interface...
//.m
-(void)return {
FirstViewController *firstview = [[FirstViewController alloc]init(withnibname:)];
[firstView.navigationController pushViewController: firstView.navigationController.topViewController animated: TRUE];
}
If I am not wrong, your UIView though is in separate files, is still added to the screen from a UIViewController class.
Simply, post a notification from UIView to your FirstViewController class where you have access to the navigation controller. Then push the SecondViewController from there.
You Can use this. It Works very well for me:-
Firstly Create Object of AppDelegate in UIView Class and initialize it. Then create Navigationcontroller object in Appdelegate.h :-
#property(strong,nonatomic) UINavigationController *navControl;
In your UIView Class implement this code where you want to push :-
ViewController *objview = [[ViewController alloc]init]; [appDelegate.navControl pushViewController:objview animated:YES];