I'm going mad using navigation controllers on the iPhone.
I have an app, with a main xib (the one with the window) inside wich I have put a NavigationController, inside wich I have a viewController. Everything is connected and the ViewController is defined with the correct inherited class name.
In the didFinishLaunchingWithOptions, i have :
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
In the .h I have :
#interface MainAppDelegate : NSObject <UIApplicationDelegate> {
IBOutlet UIWindow *window;
IBOutlet UINavigationController* navigationController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) UINavigationController* navigationController;
#end
Then in the First ViewController I have a button connected to this method :
- (IBAction) definePreferences:(id)sender {
PreferencesController *nextWindow = [[[PreferencesController alloc] initWithNibName:#"Preferences" bundle:nil] autorelease];
UINavigationController* navController = [[[UINavigationController alloc] initWithRootViewController:nextWindow] autorelease];
[self.navigationController presentModalViewController:navController animated:YES];
}
all items in the main xib seems to be connected... and retained by the properties. The AppDelegate with its window and navigationController... the Window rootviewcontroller with the same navigationController... and the file owner with the app delegate...
Everything runs fine, but the preferences window never appears...
Can you see why ?
If needed, I must say that this first view controller makes the camera interface appear and put an overlay over it. The button is onto this overlay. The imagePicker is show like this in viewDidAppear :
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
[self presentModalViewController:picker animated:YES];
[picker release];
EDIT :
In viewDidAppear, self.navigationController is ok at the start and end of method.
In definePreferences, self.navigationController is nil. Nothing is called beetween those two calls.
Nothing
EDIT :
The problem may come from the way I init the viewController on which the button is.
Here is the method called from the firstView called by the Navigation Controller.
- (void) viewDidAppear:(BOOL)animated {
UIImagePickerController* picker = [[UIImagePickerController alloc] init];
// Set the image picker source:
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.showsCameraControls = NO;
picker.navigationBarHidden = YES;
picker.wantsFullScreenLayout = YES;
// Insert the overlay
OverlayViewController* overlayController = [[OverlayViewController alloc] initWithNibName:#"Overlay" bundle:nil];
picker.cameraOverlayView = overlayController.view;
// Show the picker:
[self presentModalViewController:picker animated:NO];
[picker release];
[super viewDidAppear:YES];
}
But... how should I do ?
First, never call an IBAction setPreferences:. That violates KVC, and can eventually cause all kinds of bizarre behaviors. setX: is a reserved name for the setter of the property named x.
You should not be creating a nav controller in this method (i.e. navController). You should be using the one you created in the NIB (self.navigationController). Check if that is nil. If it is, then you either didn't set up a navigation controller in the NIB, or you didn't wire it to this view controller.
You should also verify that nextWindow is non-nil.
I've finaly solved the problem.
See https://stackoverflow.com/questions/5317968/iphone-camera-overlay-going-down-after-a-modal-view-transition
I have some hair less... :-)
Related
I am trying to load a new view when I click a button in the app.
The error I am getting is -
View Switcher[6867:207] -[UIView pushViewController:animated:]: unrecognized selector sent to instance 0x6010660
and the source code snippet is -
-(IBAction) blueButtonPressed:(id)sender{
if(self.yellowViewController == nil){
YellowViewController *yellowController = [[YellowViewController alloc] initWithNibName:#"YellowView" bundle:nil];
self.yellowViewController = yellowController;
//[yellowController release];
//[self.view addSubview:yellowController.view];
//[self.view pushViewController:self.yellowViewController];
[self.navigationController pushViewController:self.yellowViewController];
[yellowController release];
}
//[self.navigationController pushViewController:self.yellowViewController animated:YES];
}
Here is the header file I am using -
#import <UIKit/UIKit.h>
#class BlueViewController;
#class YellowViewController;
#interface BlueViewController : UIViewController {
YellowViewController *yellowViewController;
BlueViewController *blueViewController;
}
-(IBAction)blueButtonPressed:(id)sender;
#property(retain) YellowViewController *yellowViewController;
#property(retain, nonatomic) BlueViewController *blueViewController;
#end
The link to the xcode project is - https://rapidshare.com/files/2403429896/View_Switcher.zip
pushViewController is a UINavigationController method.
[self.navigationController pushViewController:self.yellowViewController animated:YES];
I'm assuming you are in a UIViewController subclass
Could you post an Xcode project I need to see this.
Ok, I've look into your code, the problem is that you don't have any navigationController. Your app is structured like a view base application not like a navigation base application.
The result is that your self.navigationController == nil, that is why that call is ignored.
In your application delegate you need some code looking like this
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:switchViewController];
navCon.navigationBarHidden = YES;
self.window.rootViewController = navCon;
[window makeKeyAndVisible];
In the applicationFinised...
In your code, when you click on your switch in the toolbar, it's "working" because your using this code :
[blueViewController.view removeFromSuperview];
[self.view insertSubview:yellowViewController.view atIndex:0];
And there is no navigationController in that process.
You should use [self.view addSubview:yellowController.view];
Best to have a navigation controller where you push and pop controllers to or from.
UIView does not have pushViewController:animated: as a method.
You can push only in UINavigationController
I have a root view controller which should load another view controller as soon as it is done loading (i.e. in the viewDidLoad method).
I am using the UINavigationController in order to push a new view controller onto the stack:
In my rootviewcontrollerappdelegate:
-(void) viewDidLoad{
LoginViewController* lvc = [[LoginViewController alloc]init];
[self.navigationController pushViewController:lvc animated:NO];
}
I have textfields and buttons in the view controller to be loaded. The above doesn't seem to work however...It loads just a blank grey screen and no UINavigation bar is present. If I comment out the second line (pushViewController line), then I see the navigation bar. So I think it is loading something, but the items in the view controller being loaded are not being shown...Any ideas why?
Check if navigationController is pointing to nil. If it does, try
[self.view addSubview:self.pushViewController.view]
I had the same problem and found the above solution here:
UIViewController -viewDidLoad not being called
Unless you're doing something tricky, you should be calling alloc on the LoginViewController class rather than a variable. Also, if you've set up LoginViewController in Interface Builder (as opposed to programmatically), you'll need to load it from an NIB:
LoginViewController *lvc = [[[LoginViewController alloc] initWithNibName:nil bundle:nil] autorelease];
[self.navigationController pushViewController:lvc animated:NO];
Have a look at initWithNibName:bundle: in the docs.
Not entirely sure what you are trying to achieve but when you instantiate LoginViewContoller it should probably look like this
LoginViewController* lvc = [[LoginViewController alloc]init];
Judging by the nature of your naming for your view controller, is your LoginViewController the first view controller for your UINavigationController?
If that is what you're trying to do, you should instead initialise your navigation controller with the LoginViewController as the root controller instead of pushing it onto the navigation stack.
UINavigationController has a method to do this:
- (id)initWithRootViewController:(UIViewController *)rootViewController
EDIT:
Well, one way you can go about it is like this.
In your application delegate .h file, you should have declared a UINavigationController.
#interface MyAppDelegate : NSObject <UIApplicationDelegate>
{
UINavigationController *navController;
}
#property (nonatomic, retain) UINavigationController *navController;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
In your App Delegate didFinishLaunching:withOption: you can create an instance of your LoginViewController there, and use that to init your UINavigation controller as the root view controller
#import "LoginViewController.h"
#implementation MyAppDelegate
#synthesize navController;
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
LoginViewController *loginController = [[LoginViewController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:loginController];
[loginController release];
[[self window] setRootViewController:navController];
[navController release];
[self.window makeKeyAndVisible];
return YES;
}
I probably have a typo here or there but that's one way I would go about doing it.
I have the following code in my AppDelegate:
#import <UIKit/UIKit.h>
#class PersonalDiarySystemViewController;
#interface PersonalDiarySystemAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
PersonalDiarySystemViewController *viewController;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet PersonalDiarySystemViewController *viewController;
#property (nonatomic, retain) UINavigationController *navigationController;
#end
#import "PersonalDiarySystemAppDelegate.h"
#import "PersonalDiarySystemViewController.h"
#implementation PersonalDiarySystemAppDelegate
#synthesize window;
#synthesize viewController;
#synthesize navigationController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Set the view controller as the window's root view controller and display.
self.window.rootViewController = self.viewController;
navigationController = [[UINavigationController alloc] initWithRootViewController:self.window.rootViewController];
navigationController.navigationBar.tintColor = [UIColor
colorWithRed:217.0/255
green:33.0/255
blue:0
alpha:1];
navigationController.navigationBarHidden = YES;
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
My rootviewcontroller tries to load another viewcontroller into the navigation controllers stack in its viewDidLoad method but for some reason the view is not getting pushed:
-(void) viewDidLoad{
lvc = [[LoginViewController alloc] init];
//lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[lvc setDelegate:self];
//[self presentModalViewController:lvc animated:YES];
[self.navigationController pushViewController:lvc animated:YES];
}
I'm getting no errors so not sure whats going on...using presentModalViewController works...so really am confused!!
You need to assign lvc to LoginViewController.
- (void) viewDidAppear
{
[self performSelector:#selector(loginCheck:) withObject:nil afterDelay:0.5];
}
- (void) loginCheck:(id)sender
{
LoginViewController * lvc = [[LoginViewController alloc] init];
//lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[lvc setDelegate:self];
//[self presentModalViewController:lvc animated:YES];
[self.navigationController pushViewController:lvc animated:YES];
}
Put your
[self.navigationController pushViewController:loginViewController];
Into the
- (void)viewDidAppear:(BOOL)animated
method. The viewControllers navigationController doesn't get loaded until then
There are two things that might go wrong.
First, you alloc the navigation controller in applicationDidFinishLaunching, I'm not quite sure which goes first, applicationDidFinishLaunching or viewDidLoad.
As you've seen, you first set your root view controller, then alloc the navigation controller, then maybe viewDidLoad launched right after you set the root view controller, then the navigation controller is allocated. so the words in viewDidLoad may not work because at that time, the navigation controller hasn't been born yet.
But I don't' quite thing the previous explanation works. it's just a possibility.
There's another strange thing, you set the navigation bar of your navigation controller hidden
navigationController.navigationBarHidden = YES;
Then it seems that the user can't pop back to the root view controller, so the navigation controller don't push the login view controller.
Meanwhile, the modal view controller can be dismissed with the navigation bar hidden or the navigation bar not allocated, so it works when you present it as a modal view controller.
but i'm still not quite sure about it since i'm now having some issues with Xcode, so i can't test the previous two ideas, sorry about that. but i still recommend that you set navigationBarHidden to NO.
- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.navController = navigationController;
[mainViewController release];
[navigationController release];
// Configure and display the window.
[window addSubview:navController.view];
[window makeKeyAndVisible];
}
- (void)viewDidLoad{
lvc = [[LoginViewController alloc] init];
[self.navigationController pushViewController:lvc animated:YES];
}
I am trying to present a image selector to my user while they are on a view presented as modal view.
I am building the view in a table view app. Right now the code runs but does not open the ImagePicker.
In DetailTableViewController.m
#implementation DetailTableViewController
There is an (+) button in the nav and when it is clicked I call
- (void)add
{
DetailTableViewController *controller = [[DetailTableViewController alloc]
initWithStyle:UITableViewStyleGrouped];
UINavigationController *newNavController = [[UINavigationController alloc]
initWithRootViewController:controller];
newNavController.delegate = self;
[[self navigationController] presentModalViewController:newNavController
animated:YES];
DetailTableViewController *controller2 = [[DetailTableViewController alloc]
initWithStyle:UITableViewStyleGrouped];
imgPicker = [[UIImagePickerController alloc]
initWithRootViewController:controller2];
imgPicker.allowsEditing = YES;
imgPicker.delegate = self;
//______________HERE I CREATE THE INTERFACE FOR THIS VIEW IN CODE__________________
NSLog(#"Load add View");
}
One of the button on this page is a select image button which is here:
- (IBAction)grabImage {
[newNavController pushViewController:imgPicker animated:YES];
NSLog(#"grabImage");
}
This does not present the imgPicker view. But the button click is logged.
I have in the top of file: DetailTableViewController.m
#implementation DetailTableViewController
#synthesize imgPicker;
In DetailTableViewController.h
#interface DetailTableViewController : UITableViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextViewDelegate> {
MWFeedItem *item;
NSString *dateString, *summaryString;
IBOutlet UIWebView *webview;
IBOutlet UIButton *dismissViewButton;
UIImagePickerController *imgPicker;
UINavigationController *newNavController;
IBOutlet UIButton *upload;
IBOutlet UIButton *doneEdit;
IBOutlet UIImageView *image;
}
How can I make the imgPicker display?
I have tried:
using presentModalViewController instead of push in grabImage
List item many combinations of which controller imgPicker is presented to. With some
I get the error: (Application tried to present a nil modal view controller on target)
several variations from this question:
iPhone modal view inside another modal view?
UPDATED including corrections from #aBitObvious, but the issue remains.
#aBitObvious pointed me to the answer. The local override turned out to be the answer but not on imgPicker but on newNavController.
Thanks again!
I'm using two UIViewController in Application Delegate and navigating to UIViewController using presentmodalviewcontroller. But Problem is that presentmodalviewcontroller works for first time UIViewController and when i want to navigate to second UIViewController using presentmodalviewcontroller then its showing first UIViewController.
The following is the code:-
-(void)removeTabBar:(NSString *)str
{
HelpViewController *hvc =[[HelpViewController alloc] initWithNibName:#"HelpViewController" bundle:[NSBundle mainBundle]];
VideoPlaylistViewController *vpvc =[[VideoPlaylistViewController alloc] initWithNibName:#"VideoPlaylistViewController" bundle:[NSBundle mainBundle]];
if ([str isEqualToString:#"Help"])
{
[tabBarController.view removeFromSuperview];
[vpvc dismissModalViewControllerAnimated:YES];
[viewController presentModalViewController:hvc animated:YES];
[hvc release];
}
if ([str isEqualToString:#"VideoPlaylist"])
{
[hvc dismissModalViewControllerAnimated:YES];
[viewController presentModalViewController:vpvc animated:YES];
[vpvc release];
}
}
Can Somebody help me in solving the problem?
You're making a new hvc and vpvc each time you run this function.
The first time through, I assume you call removeTabBar:#"Help", it makes a hvc and vpvc and then shows the correct one.
The second time you call it removeTabBar:#"VideoPlayList", you are making a new hvc and vpvc. This means that when you call hvc dismissModalViewController:YES]; you're not removing the one you added before, you're removing the new one that you just made which isn't being displayed at all!
To solve this you need to make your two controllers as properties in your app delegate and create them in the applicationDidFinishLaunching method.
Add these into your app delegate's .h file:
#class MyAppDelegate {
HelpViewController *hvc;
VideoPlaylistViewController *vpvc;
}
#property (nonatomic, retain) HelpViewController *hvc;
#property (nonatomic, retain) VideoPlaylistViewController *vpvc;
#end
and in your app delegate's .m file :
- (void)applicationDidFinishLaunching:(UIApplication *)application {
...
self.hvc = [[[HelpViewController alloc] initWithNibName:#"HelpViewController" bundle:nil] autorelease];
self.vpvc = [[[VideoPlaylistViewController alloc] initWithNibName:#"VideoPlaylistViewController" bundle:nil] autorelease];
...
}
and remove the first two lines in removeTabBar