I've written an app that launches the camera directly. I want to launch a view with settings as a modal view of UIImagePickerController, but directly after its presentation, it's disappearing.
What is the correct way to do this? I want the app to be full screen so I am using an overlay view on the UIImagePickerController.
Any ideas? I am targeting iOS7 or later.
I've added some source. This is called from my UIImagePickerController derived class.
SettingsTableViewViewController *controller = [[SettingsTableViewViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
[self presentViewController:navController animated:YES completion:nil];
I have a Tab Bar application that shows several tabs. I case of notification I want user to be directed to a view controller with the ability to push "Back".
When my app was only Navigation controller app, I used this code in my AppDelegate:
UIStoryboard *mainStoryboard = self.window.rootViewController.storyboard;
DetailViewController *detailViewController = (DetailViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"detailViewController"];
[(UINavigationController*)self.window.rootViewController pushViewController:detailViewController animated:NO];
This code used to work fine until I converted my app to be Tab Bar. Seems like the "self.window.rootViewController" is not longer of type "UINavigationController" and therefore calling "pushViewController" generates an exception saying method doesn't exist.
Any way to make this work on a Tab Bar application?
Thanks
You should present your notification controller as modal (presentViewController:animated:completion:), and inside that controller you provide a way to close it, probably a button on top bar.
EDIT:
Thanks for Dimitry's answer I was able to go on the right track. I just had to make a small trick in order to preserve the top navigation bar and the bottom tool bar. I did it by using a "UINavigationController" instance. Here is the code:
UIStoryboard *mainStoryboard = self.window.rootViewController.storyboard;
DetailViewController *detailViewController = (DetailViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: #"detailViewController"];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
navigationController.navigationBar.tintColor = [UIColor blackColor];
navigationController.toolbar.tintColor = [UIColor blackColor];
[self.window.rootViewController presentViewController:navigationController animated:YES completion:NULL];
My main menu (a ViewController) is embedded in a NavigationController that I added in the storyboard in Xcode4.
I have a button in my menu, displaying a new view. To display it I use :
- (IBAction) display : (id) sender
{
if(!anotherView) anotherView = [[AnotherView alloc] initWithNibName:#"AnotherView" bundle:nil];
[self presentModalViewController:anotherView animated:NO];
}
My other view is correctly displayed with all its objects and elements. Excluding my NavigationController's bar, that doesn't appear. Why ?
Thanks for your advices
You are presenting the view modally what you probably meant was
[self.navigationController pushViewController:anotherView animated:YES]
of course what you really want to do is not mix and match storyboard and non storyboard flows unnecessarily like this and have the storyboard do this for you
you are presenting your viewController modally. If you want to use the navigation controller you have to push your view onto the navigation stack.
replace
[self presentModalViewController:anotherView animated:NO];
with
[self.navigationController pushViewController:anotherViewController animated:YES];
You can still present your view modally without losing the navigation bar. Try this code:
AnotherView *tempAnotherView = [[AnotherView alloc] initWithNibName:#"AnotherView" bundle:nil];
[self setAnotherView:tempAnotherView];
[tempAnotherView release];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:self.anotherView] autorelease];
[self.navigationController presentModalViewController:navController animated:YES];
Hope it helps! :)
Is it impossible to present a popover controller from a view controller that's presented as UIModalPresentationFormsheet? or am I missing something?
This code works fine on a non-modal view controller, and displays the popover correctly.(WEPopoverController is a custom implementation from here.)
GenericDataTableViewController *genericDataController = [[GenericDataTableViewController alloc] initWithNibName:#"GenericDataTableViewController" bundle:[NSBundle mainBundle]];
genericDataController.dataSource = [NSMutableArray arrayWithObjects:#"asli", nil];
genericDataController.delegate = self;
genericDataController.contentSizeForViewInPopover = CGSizeMake(300, 46 * [genericDataController.dataSource count]);
self.popoverController = [[[WEPopoverController alloc] initWithContentViewController:genericDataController] autorelease];
self.popoverController.delegate = self;
[self.popoverController presentPopoverFromRect:((UIButton *)sender).frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
[genericDataController release];
But when I put this inside the modal view controller, this presents the popover below the modal controller, i.e. on the view controller that presents the modal one. So it cannot be seen by the user.
How can I solve this?
The answer is explained in the comments of the question but I'm summarizing it here for a cleaner Q&A.
There aren't any restrictions about displaying a popover controller from inside a form sheet, if your popover controller is UIPopoverController. My problem was due to the implementation of WEPopoverController.
So, sacrifice the visual experience and continue with the good old UIPopoverController.
I have a navigation based app with a navigation bar, but there are a few instances where instead of pushing a view controller onto the stack, I need to present the view controller modally. The problem is that when I dismiss the modal view controller, everything functions as expected except that the navigation bar is hidden and the (parent view) has been resized, which is the expected behavior according to the docs. So I figured I could simply call a built-in method to unhide the navigation bar. I have already tried
[self.navigationController setNavigationBarHidden:NO];
as well as the animated version without success.
The documentation talks about this in the method
presentModalViewController: animated:
in the discussion section where it says,
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen" and "Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy."However, the docs didn't clue me in as to how to undo this process after dismissing a modal view.
Has anyone else experienced this and found a solution?
Edit: I am having this same problem, so instead of asking my own question I am sponsoring a bounty on this one. This is my specific situation:
In my case, I am presenting an Image Picker in a Modal View Controller, over a Navigation Controller:
-(void) chooseImage {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
imagepicker = [[UIImagePickerController alloc] init];
imagepicker.allowsEditing = NO;
imagepicker.delegate = self;
imagepicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagepicker.navigationBar.opaque = true;
imagepicker.wantsFullScreenLayout = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if (self.view.window != nil) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:imagepicker];
[popoverController presentPopoverFromBarButtonItem:reset permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
} else {}
} else {
[self.navigationController presentModalViewController:imagepicker animated:YES];
}
}
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.popoverController dismissPopoverAnimated:true];
} else {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
//Save the image
}
-(void) imagePickerControllerDidCancel:(UIImagePickerController *)picker {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.popoverController dismissPopoverAnimated:true];
} else {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
}
Make sure you a presenting AND dismissing the modalViewController from the UINavigationController, like so:
// show
[self.navigationController presentModalViewController:vc animated:YES];
// dismiss
[self.navigationController dismissModalViewControllerAnimated:YES];
If your view controller is actually on the UINavigationController's stack then this is the correct way to handle the presentation and dismissal of the modal view controller. If your UINavigationBar is still hidden, there is something else funky going on and we would need to see your code to determine what is happening.
Edit
I copied your code into an app of mine and the UIImagePickerController successfully presented and dismissed and my UINavigationController's UINavigationBar was still there. I truly believe that the problem lays elsewhere in your architecture. If you upload a zip w/ an example project I will take a look.
Simply try following code it will work
SettingsViewController *settings = [[SettingsViewController alloc] init];
UINavigationController *navcont = [[UINavigationController alloc] initWithRootViewController:settings];
[self presentModalViewController:navcont animated:YES];
[settings release];
[navcont release];
One need to present the navigation controller in order to have navigation bar on the presented controller
I think I've seen this behavior when presenting a view controller on the wrong VC. Are you calling presentModalViewController on the navigation controller or the individual VC?
Try calling it from the navigationController if you aren't already.
[self.navigationController presentModalViewController:myVC animated:YES];
If you present a controller as model, View controller will appear to total view.
If you want to access the navigation controller properties over the model view, You need to create another navigation controller reference and it continues as previous.
This may be useful for you.
Check this out. This is Apple's Documentation under UIViewController Class Reference:
It clearly mentions that modal view always presents in full screen mode, so it is obvious that navigation bar will be hidden. So put the seperate navigation bar on modal view to navigate back.
presentModalViewController:animated:
Presents a modal view managed by the given view controller to the user.
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
Parameters
modalViewController
The view controller that manages the modal view.
animated
If YES, animates the view as it’s presented; otherwise, does not.
Discussion
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen. On iPad, the presentation depends on the value in the modalPresentationStyle property.
Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy. The view is animated according to the transition style specified in the modalTransitionStyle property of the controller in the modalViewController parameter.
Availability
Available in iOS 2.0 and later.
Hope this helps you understand that hiding the whole view along with navigation controller is default behaviour for modal view so try putting a seperate navigation bar in modal view to navigate.
You can check it further on this link
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
AddContactVC *addController =[self.storyboard instantiateViewControllerWithIdentifier:#"AddContactVC"];
UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:addController];
[self presentViewController:navigationController animated:YES completion: nil];
working for me shows navigation bar
Emphatic and Devin –
As I started reading through the Apple docs to get familiar with the problem, I noticed that the method you're using, presentModalViewController:animated:, appears to be deprecated in favor of presentViewController:animated:completion:. Perhaps you should try to use that method instead.
For your convenience, take a look for yourself:
presentModalViewController:animated: reference
I'll try to put together a quick test program to see whether what I've said above is actually true. But give it a shot – maybe it'll help!
Xcode has a template that does pretty close to what you're doing. from the results, i don't think you should be attempting to perform [self.navigationController presentModalViewController:vc] and [self.navigationController dismissModalViewControllerAnimated:] , but rather simply [self presentModalViewController:] and [self dismissModalViewControllerAnimated:] .
to see how the template does this for yourself, you can use the new project wizard in xcode 4.3 . perhaps it will provide some guidance:
from that choice, choose Next, then give your test project a name, choose "Universal", turn off automatic reference counting, hit next, save where you want it.
now, click on the target and switch the deployment target to 4.3 (or 4.0 if you prefer) for your testing purposes, and switch to your device or the iOS 4.3 simulator .
finally, substitute the following code in applicationDidFinishLaunching:withOptions: in the created AppDelegate.m:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainViewController_iPhone"
bundle:nil] autorelease];
} else {
self.mainViewController = [[[MainViewController alloc] initWithNibName:#"MainViewController_iPad"
bundle:nil] autorelease];
}
UINavigationController* navigationController
= [[UINavigationController alloc] initWithRootViewController:self.mainViewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
now, when i run this, it doesn't hide the navigationBar. and in the created MainViewController.m from the template, you'll see how it presents the modal view controller and dismisses it from the controller itself and not from the navigation controller. for good measure, to make the template code more like your own, go into MainViewController.m and delete the line that sets the modal view controller transition style ...
(of course, in iOS 5, with storyboards, the same thing can all be accomplished with modal segues ... which is how i've done this for apps that i'm not supporting for pre-5.0 that present a modalViewController in this fashion.)
One of the best solution it to use this Category MaryPopin
https://github.com/Backelite/MaryPopin