I have the following code pushing a UIViewController. This code is a target method that gets executed when a UIButton is pressed:
-(void)pushNavigationController
{
ParameterListerViewController *plvc = [[ParameterListerViewController alloc] init];
UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:plvc];
self.navigationController.navigationBarHidden = YES;
plvc.numberOfParameters = [[numberOfTrialsField text] intValue];
NSLog(#"about to push the navigation controller");
[self.navigationController pushViewController:nvc animated:YES];
}
It gets until the NSLog statement, but after that, the view controller never gets pushed and the app just crashes. Here is the header file of ParameterListerViewController:
ParameterListerViewController.h
-------------------------------
#interface ParameterListerViewController : UIViewController<UITextFieldDelegate>
{
UIScrollView* scrollView;
}
#property(nonatomic) NSInteger numberOfParameters;
#end
Here's the header file which contains the UIButton and the respective target method which contains the code for pushing the navigation controller.
SettingsViewController.h
------------------------
#interface SettingsViewController : UIViewController <UITextFieldDelegate, UIPickerViewDelegate, UITableViewDelegate, UITableViewDataSource>
{
id <SettingsViewDelegate> delegate;
}
#end
And here's the header file of a class object that DOES GET PUSHED:
#interface ItemViewController : UITableViewController
{
}
#end
Any suggestions?
Your nav controller's view has to be in the view hierarchy.
Unless the nav controller is set as the rootViewController of a UIWindow, it needs to be explicitly added.
Try this:
[self.view addSubview:self.nvc.view];
If this is the case, you won't need to do the pushViewController - the plvc will already be visible.
Related
I have a Controller A and there is a UIButton, which on click I am presenting a new Controller B. But the problem is that the controller B is first embedded with a NAV. So ultimately I am presenting the UINavigationController.
Now there is a UIButton in Controller B on which the controller will dismiss and a delegate should be passed on controller A with some message
Controller A UIButtonCode
- (IBAction)summaryButtonClick:(id)sender {
UIStoryboard* storyBoard=[UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController* summaryVC=[storyBoard instantiateViewControllerWithIdentifier:#"SummaryNavVC"];
[self presentViewController:summaryVC animated:YES completion:nil];
summaryVC=nil;
}
Now Controller B
.h file
#import <UIKit/UIKit.h>
#protocol SummaryViewWhatsNewDelegate <NSObject>
#required
- (void) SummaryViewWhatsNew:(NSString*)title;
#end
#interface SummaryViewController :
UIViewController<UITableViewDataSource,UITableViewDelegate>
{
id <SummaryViewWhatsNewDelegate> _delegate;
}
#property (nonatomic,strong) id delegate;
#property (weak, nonatomic) IBOutlet UITableView *summaryTableView;
- (IBAction)closeSummaryView:(id)sender;
#end
.m
//Button Click
[self dismissViewControllerAnimated:YES completion:^{
[_delegate SummaryViewWhatsNew:#"Sales Triggers Filter"];
}];
I have already made the implementation of delegate in my Controller A
.h
#interface ControllerA : UIViewController<SummaryViewWhatsNewDelegate>
.m of Controller A
#pragma mark -ControllerB Delegate
-(void)SummaryViewWhatsNew:(NSString *)title{
NSLog(#"Delegate Called");
}
In this case I know I haven't provided the delegate.self part as I am presenting the NAV controller and not the Controller B
So I made a Object in viewDidLoad and Controller *B and set the delegate to self. But it doesn't work and delegate is never called
On the other hand if I only present the Cntroller B without Navigation and just before presenting I keep the b.delegate=self, it works.
Another alternate can be firing Notifications. But I want to work with delegates.
So is there any way to call the delegate of the presented view controller which is embedded by Nav. Any help will be highly appreciated.
Well I got the answer
We have to fetch the Controller object from NAV
Where I a presenting I just need to add these lines and it worked
UIStoryboard* storyBoard=[UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController* summaryVC=[storyBoard instantiateViewControllerWithIdentifier:#"SummaryNavVC"];
//Add These lines in order to get the object of Controller B.
// SummaryViewController is my Controller B
SummaryViewController* summary=[[summaryVC viewControllers] objectAtIndex:0];
summary.delegate=self;
[self presentViewController:summaryVC animated:YES completion:nil];
And it worked.
I have two view controllers. We'll call them listViewController and mapViewController. The listViewController shows first, a user taps a button that shows the mapViewController. The user taps a button on a annotation which is where my problems start.
When the user taps a button on mapViewController, I would like to call a method listViewController and dismiss mapViewController. To do this I am using this code:
mapViewController.m
listViewController* lvc = [[listViewController alloc] initWithNibName:nil bundle:nil];
[lvc getInformation:StringParameter];
[self dismissViewControllerAnimated:YES completion:nil];
However, when executing getInformation it seems that the listViewController class has been dealloc'd because all of the objects that I initialized in the viewDidLoad on listViewController are now nil including self, which just breaks everything.
I assume I'm creating the listViewController object incorrectly in mapViewController. I've tried it with a nil for nibName with the same result.
Ok, Let me clear one thing. On listViewController, you presentViewController a mapViewcontroller right? And you want invoke getInformation of the instance from mapViewController. In the code you're added, you instantiate listViewController again. You have 2 different instance of listViewController.
One option is to use a delegate pattern:
In your MapViewController.h file:
#protocol MapViewControllerDelegate <NSObject>
-(void)dismissMe;
-(void)getInformation:(NSString *)stringParameter;
#end
#interface MapViewController : UIViewController
#property (weak)id <MapViewControllerDelegate> delegate;
#end
In your MapViewController.m file:
-(void)annotationButtonTap:(id)button
{
[self.delegate getInformation:stringParameter];
[self.delegate dismissMe];
}
In your ListViewController.h
#import "MapViewController.h"
#interface ListViewController : UIViewController <MapViewControllerDelegate>
-(void)dismissMe
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)getInformation:(NSString *)stringParameter
{
//do whatever you plan with stringParameter
}
And somewhere in you ListViewController.m file where you create the MapViewController instance:
mapViewController = [[MapViewController alloc] initWithNibName:#"MapViewController" bundle:nil];
mapViewController.delegate = self; //make sure you do this
I have a UIImageView with a custom class. When the image is pressed the class should push a new view controller, however I don't seem to be able to get a reference to the current UINavigationController. I would usually do self.navigationController, but here I can't.
I tried the following code but it doesn't work:
[self.window.rootViewController.navigationController pushViewController:browser animated:YES];
Give your Custom Image View a delegate:
#protocol CustomImageViewDelegate;
#interface CustomImageView : UIImageView
#property (weak, nonatomic) id<CustomImageViewDelegate> delegate;
#end
#protocol CustomImageViewDelegate
- (void)imageViewPressed:(CustomImageView *)imageView
#end
Make you view controller the delegate. When the image is pressed, you do [self.delegate imageViewPressed:self.
Your view controller will have the implementation:
- (void)imageViewPressed:(CustomImageView *)imageView
{
[self.navigationController pushViewController:browser animated:YES];
}
Or give your view a Navigation Controller property:
#interface CustomImageView : UIImageView
#property (weak, nonatomic) UINavigationController navigationController;
#end
Then you can use [self.navigationController pushViewController:browser animated:YES] directly on your Custom Image View.
You'll have to set the navigationController property, iOS won't do it for you.
On your controller add the line
self.yourCustomImageViewProperty.navigationController = self.navigationController;
This is a very basic response, but I hope it steers you in the right direction.
First make UIImageView to UserInteractionEnabled = YES.
Check that self.window.rootViewController.navigationController is
nil or not .
If the root view controller is already a navigation controller, then you could do this:
UINavigationController *nav = self.window.rootViewController;
[nav pushViewController:browser animated:YES];
I have two views a levelComplete view and a levelSelector view. What I would like to do is when the levelComplete shows or the ViewDidLoad occurs on that view I would like to send a delegate to the level selector to show a button in the view and then make that button UserInteractionEnabled so then I will then be able to programme that button to do something if its not hidden.
You want to necessarily do it via a delegate. Coz you can do it in a simpler way as well. When you call your secondView, just tell your button to hide. So your modified code to calling the second view controller becomes:
-(IBAction)passdata:(id)sender {
secondview *second = [[secondview alloc] initWithNibName:nil bundle:nil];
self.secondviewData = second;
sender.hidden=YES;
secondviewData.passedValue = textfield.text;
[self presentModalViewController:second animated:YES];
}
And then you can set it to visible when your view loads up again using viewDidLoad. I can tell you how to do it via delegates if you need. Lemme know what works best.
EDIT - Solution by Delegates
Your secondView's Header file will be as follows:
#protocol SecondViewHandlerDelegate <NSObject>
- (void)viewHasBeenLoaded:(BOOL)success;
#end
#interface secondview :UIViewController {
IBOutlet UILabel *label;
NSString *passedValue;
}
#property (nonatomic, retain)NSString *passedValue;
-(IBAction)back:(id)sender;
#end
Then, in the implementation file of secondView(.m), synthesise the delegate first by #synthesize delegate; . After this, in your viewDidLoad of secondView, add the following line:
[[self delegate] viewHasBeenLoaded:YES];
That should be enough for your secondView. Now onto the firstViewController, perform the following steps:
In the header file (.h), import your second view and implement the protocol:
#interface ViewController :UIViewController <SecondViewHandlerDelegate>{
..
..
}
In the implementation file (.m) of your firstViewController, implement this method:
- (void)viewHasBeenLoaded:(BOOL)success
{
NSLog("Delegate Method Called");
[myButton setHidden:YES];
}
And finally, in your code when you call the secondView, add this line:
secondview *second = [[secondview alloc] initWithNibName:nil bundle:nil];
second.delegate = self;
...
That should solve your purpose. I'd appreciate if you could mark the answer as correct as well. Thanks :)
There is a current view as UIViewController which call "LoginView" but I'm not in, I'm in a NSObject class and I want to call, display an other UIViewController which is call "MapView". How can I do this?
The problem is like above screenshot.
At your IBAction or specific method write this:
UIWindow *window=[UIApplication sharedApplication].keyWindow;
UIViewController *root = [window rootViewController];
UIStoryboard *storyboard = root.storyboard;
CustomViewController *vcc =(CustomViewController *) [storyboard instantiateViewControllerWithIdentifier:#"storyBoardID"];
[root presentModalViewController:vcc animated:YES];
I am assuming you're trying to access your UIViewController member from a UIViewController class from a NSObject class. Easy just pass UIViewController member to the NSObject class. In this case a self. What that lets you do is you can change, edit, remove, whatever you want to do in your UIView from another class. The following is an example of that.
Calling the NSObject Class from your UIViewController class
#implementation myViewControllerClass
- (void) viewDidLoad {
//Pass in the UIViewController object, in this case itself.
[[myNSOBjectClass alloc] startViewController:self];
....
}
Then from your NSObject
#interface myNSOBjectClass{
//Global access to the view controller.
UIViewController *viewController;
}
...
#implementation myNSOBjectClass
...
//function that the caller calls to pass their UIViewController object
- (void)startViewController:(UIViewController *)callerViewController{
viewController = [[UIViewController alloc]init];
//puts the caller's view controller to the global member.
viewController = callerViewController;
...
}
Now you have the view controller at your fingertips!
Cheers :)!
I used like this in my NSObject class:
[[[UIApplication sharedApplication] delegate].window.rootViewController presentViewController:yourMapViewContorller animated:YES completion:nil];
I hope it's useful.
You shouldn't be instantiating and displaying view controllers from within a model. Views should be driven by models.
In this case you mentioned LoginView as your starting point. When some condition is satisfied (successful login perhaps?) you should update the underlying model accordingly, and then display the MapView.
From within LoginView:
MapView *mapView = [[MapView alloc] init];
If your app uses a navigation controller:
[self.navigationController pushViewController:mapView animated:YES];
Otherwise:
[self presentViewController:mapView animated:YES completion:<nil or block>];
Try this Code. It'll help to you......
In your button click action You have to send your UINavigationController & current ViewController. Because NSObject class not found that controller.
In your Button Action put this Code:
[demo login_method_called:self.navigationController withCurrentViewController:self];
In your NSObject .h class put this code:
#import <Foundation/Foundation.h>
#import "Home_ViewController.h"
#interface Method_Action_class : NSObject
- (void)login_method_called:(UINavigationController*)navigation withCurrentViewController:(UIViewController*) controller;
#end
In your NSObject .m class put this code:
#import "Method_Action_class.h"
#implementation Method_Action_class
-(void)login_method_called:(UINavigationController*)navigation withCurrentViewController:(UIViewController*) controller
{
Home_ViewController *home = [[Home_ViewController alloc] initWithNibName:#"Home_ViewController" bundle:nil];
[navigation pushViewController:home animated:YES];
}
#end
And Build your code.
I have created an obersver in view controller class and declare a method of push view controller and post notification using NSNotification centre from NSObject subclass and it is working well.
in view controller:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(dismissPickerView) name:kNotificationDismissPicker object:nil];
in subclass of NSOject:
[[NSNotificationCenter defaultCenter] postNotificationName:kMoveToAchievementView object:nil];