UiImagePickerController - Additional Preview Screen With Overlay - cocoa-touch

The latest "Yelp" app provides "Add Business Photo" functionality. After taking a photo the preview screen is displayed as usual. However tapping the "use" button displays what appears to be the same preview screen with an overlay containing buttons and a textfield to enter a caption. I've read that the way to display an overlay on the preview screen "ONLY" is as follows:
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
if (!viewController)
return;
UIView* controllerViewHolder = viewController.view;
UIView* controllerCameraView = [[controllerViewHolder subviews] objectAtIndex:0];
UIView* controllerPreview = [[controllerCameraView subviews] objectAtIndex:0];
[controllerCameraView insertSubview:self.overlayView aboveSubview:controllerPreview];
}
I've yet to get this to work :) however I'm now debating on what approach to use in order to display the preview screen twice ie. once normally and then afterward with overlay?
I dont know the ins and outs of UIImagePickerController yet and and I'm wondering if its possible to insert the overlay above the preview and re-display the preview after the preview has been displayed (not sure if thats possible) or create and display a entirely new view (copy of preview with overlay applied)? (not sure how I would do that either).
Thanks in advance for your input..

The UIImagePickerController is a navigation controller. That means you can push things on and off of the view controller stack controlled by the image picker. When you get the imagePickerController:didFinishPickingMediaWithInfo: notification, just push another view onto the image picker stack like this.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSURL *imageURL = [info objectForKey:UIImagePickerControllerMediaURL];
MyCustomPreviewController *customPreview = [[MyCustomPreviewController alloc] initWithImageURL:imageURL];
[picker pushViewController:customPreview animated:YES];
}

Related

iOS7 - popToRootViewControllerAnimated not doing anything

I have looked around but haven't found a satisfying answer. My problem is that whenever I call popToRootViewControllerAnimated:(BOOL) it is not doing anything. When I NSLog it, it logs (null).
Let me back up a bit here. I have a table view controller that has a list of things, at the navigation bar up top there is an option to add and that takes me to a new view controller with a segue "Present as PopOver" which gets rid of the principal or main navigation bar. So I made one manually and added 2 bar button items "Cancel" and "Add". When "Cancel" is tapped, it should take the user back to the table view controller and discard changes, when "Add" button is tapped, it should also take user back to the previous table view controller with the changes. But it's not doing anything.
Here is my code.
- (IBAction)cancelButton:(UIBarButtonItem *)sender {
UINavigationController * navigationController = self.navigationController;
NSLog(#"%#", navigationController);
NSLog(#"cancel tapped though");
ListingTableViewController *rootController = [[ListingTableViewController alloc] init];
[navigationController popToRootViewControllerAnimated:NO];
[navigationController pushViewController:rootController animated:YES];
}
As far as the segue, this view controller is not connected to anything, or should I connect it? This is a noobish question indeed. Here is my xcode screenshot.
Check this link for the screenshot of the storyboard
http://i.stack.imgur.com/lqnCF.png
You must call
- (IBAction)cancelButton:(UIBarButtonItem *)sender {
NSLog(#"cancel tapped though");
[self dismissViewControllerAnimated:YES completion:nil];
}
instead of popToRootViewControllerAnimated because your VC presented and not pushed!
When presenting a view, you are not pushing it in your navigation controller, but having it presented. To dismiss it, try using [self.presentingViewController dismissViewControllerAnimated:NO completion:nil].

Application tried to present modally an active controller : UIImagePickerController

I'm struggle at this for 2 days and believe that this is the moment I should call for help. After I search SOF for a while, none of any answer could solve my problem. Here are my application ...
In the application,
Device is iPad, iOS 6
RootViewController is NavigationController
TopViewController is TabBarController
In this TabBarController, I present a popoverController from right bar button of navigation bar
In presenting popover there is a button to allow user to pick image from by taking new one or pick from existing.
To pick new one, I presentViewController UIImagePickerController to allow user to take photo with divice camera. presentModalViewController:animated: if iOS < 6, and presentViewController:animated:completion: for iOS > 6
I also hide Status Bar before presentation
To select from existing photo, I do presentPopoverFromBarButtonItem:permitArrowDirections:animated:
PopoverViewController also referencing by A TabBarController
Here is the issue
Present UIImagePickerController will always failed if user try to pick new one first with exception "Application tried to present modally an active controller <[name of view controller that try to present]>"
BUT, if user try to pick image from camera roll for once and then try to take new one again, it won't fail.
Here are what I tried
present from RootViewController
present from TopViewController (TabBarController)
present from popoverViewController itself
present from a tab of TabBarController
hide popoverViewController before presentation
resignFirstResponder from a textField in popoverViewController
Here is the current code I'm using
// PopoverViewController, presented by a tab in TabBarController
- (IBAction)takePhoto:(id)sender {
[self.delegate takePhotoWithDeviceCamera];
}
// A Tab in TabBarController, delegate of popoverViewController
- (void)takePhotoWithCamera {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
if ([UIDevice OSVersion] < 6.0) {
[self presentModalViewController:cameraPicker animated:YES];
} else {
[self presentViewController:cameraPicker animated:YES completion:nil];
}
}
Any idea what would cause this error? Any suggestion are welcome. Thank you.
Got the same trouble than you and finally got the solution based on #CainaSouza's answer. I've been working with Xamarin.iOS so I'll make my answer in C#, but it can be easily translated to Objective-C.
I'm using the same code as #CainaSouza to call the controller:
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController (customController, true, null);
And then I add the following code to my custom RootViewController:
public override void PresentViewController (UIViewController viewControllerToPresent, bool animated, Action completionHandler)
{
if (PresentedViewController != viewControllerToPresent) {
base.PresentViewController (viewControllerToPresent, animated, completionHandler);
}
}
The trick is to check if you haven't presented that UIViewController before.
I know it's an old question, but hope it will help someone. :)
Present the imagePicker controller in a popoverController(in case of iPad). This will not give you that error.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:picker];
[popover presentPopoverFromRect:self.selectedImageView.bounds inView:self.selectedImageView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
self.popOver = popover;
}
else {
[self presentModalViewController:picker animated:YES];
}
Best Regards.
Have you tried to present it like this?
[self.view.window.rootViewController presentModalViewController:cameraPicker animated:YES];
My guess is that the cameraPicker instance is not correctly allocated/released. Try creating the cameraPicker inside your - (void)takePhotoWithCamera method rather than relying on a previously created instance. You'll get a handle to the picker instance in the callback methods...
I had the same problem - I wanted users to take photos using a full screen view (i.e. call presentViewController and pass UIImagePickerController controller instance) and select existing photos from a popover (I associated it with a popover using initWithContentViewController). I reused the same instance of UIImagePickerController for both camera and popover and it threw the same exception if I tried to run a camera before opening a popover.
I turned out to cause a problem and my solution was simply to have two instances of UIImagePickerController - one for camera (which I presented from a main view) and another one for popover. It works so far. :-)
Not sure if it is still actual for the original poster, but hopefully it will help anyone else who encounter this discussion.

Hiding Master View Controller in SplitView regardless of device orientation

I've found lots of people asking for information on how to have the Master view displayed both in landscape and portrait orientation, but what I am trying to do is to having the right master view hidden regardless of the devices orientation and popping in from the side by using a navbar button.
What would help me enormously would be if someone could tell me where the logic for hiding the master view is located/executed when the device reorients. I've been looking at the template that comes with Xcode, Master/detail view for iOS, and I noticed these two following methods are declared in the AppDelegate.m file but I can't seem to find out where they are being executed from:
//Called when a button should be added to the nav bar for a view that is hidden
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController: (UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.title = NSLocalizedString(#"Master", #"Master");
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
}
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
// Called when the view is shown again in the split view, invalidating the button and popover controller.
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.masterPopoverController = nil;
}
All help would be appreciated.
You actually have no control over a UISplitViewController. The master view is always present in landscape view, and there is no possible way of changing this.
However, "Matt Gemmell created an excellent custom splitViewController called 'MGSplitViewController'. It is very easily implemented, heavily commented, and contains a lot of excellent features not found with a normal splitViewController (hide master view on landscape view, change placement of the split in landscape view, allow user to change size of split fluidly during runtime, etc)."
Info and demo: http://mattgemmell.com/2010/08/03/mgsplitviewcontroller-updated/
Straight to the source: https://github.com/mattgemmell/MGSplitViewController/
-=-=-=-=-=-=-=-=-=-=-=-
I've posted this before in a similar (but different) question with the same answer here:
How to hide master view in UiSplitviewcontroller in ipad
-=-=-=-=-=-=-=-=-=-=-=-
UPDATE:
In iOS 5.0 and beyond, they have finally added functionality to hide master view in landscape!
-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return YES;
}
Reference:
splitViewController in Ipad that doesnt hide in portrait

UIView is shown displaced to the top

I have a simple app that has two view controllers. Both of them have a UINavigationBar at the top, as a header. The second UIViewController is displayed as a modal view, when the user clicks on a button on the first one.
When my app first launches, the initial view doesn't completely cover the main UIView and seems "pushed" to the top (see image below).
After I click on the "instructions" button, which displays another view with presentModalViewController:animated:, and dismiss the modal ViewController, everything is displayed correctly.
Anybody knows what I might be doing wrong?
I have nothing in viewWillAppear, and this is my viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
if (!self.model) {
self.model = [[FRRSushiRiceModel alloc] init];
[[self.header.items objectAtIndex:0] setTitle: #"Perfect Sushi Rice: Ingredients"];
}
}
and my application:didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Create and add the main controller (ingredients)
self.ingredientsController = [[FRRIngredientsViewController alloc] init];
[window addSubview:self.ingredientsController.view];
[window makeKeyAndVisible];
return YES;
}
This small project reproduces this behavior:
Test Case
Did you untick the "Wants Full Screen" setting in IB, either for the UINavigationController or UIViewController?
I found the error, guys.
Basically I was trusting the system to correctly set the frame of my views to match the usable portion of the screen. This works when you add it to some controller of controllers (such as UINavigationController), or add it via IB.
If you add your controllers programmatically, you need to set the view's frame explicitly. A good default is:
[[UIScreen mainScreen] applicationFrame]
represents the part of the screen available to applications: the whole screen minus the status bar.

How to open an UIView in fullscreen mode with a tabbar?

this is my problem.
I have a tabBar application.
In first tab, i have a table.
On click on table it shows a modal
view.
To go back from modal view to first
view, i use
[self presentModalViewController:nw animated:YES];
The problem is that if i click on the tabbar while is opened a modal view, it opens second view, but first view's table don't work because the modal view is still opened althoug it appear as closed.
It's a way to open modal view in fullscreen covering the tab bar?
Or also to check if modal view is closed or not from another view?
EDIT:
I tried with all of this code:
nw = [[NewsViewController alloc] initWithNibName:#"NewsViewController" bundle:nil];
nw.modalInPopover = YES;
nw.wantsFullScreenLayout = YES;
nw.hidesBottomBarWhenPushed = YES;
nw.contentSizeForViewInPopover = CGSizeMake(320, 480);
nw.modalPresentationStyle = UIModalPresentationFullScreen;
nw.view.frame = [[UIScreen mainScreen] applicationFrame];
[nw.view setNeedsLayout];
but nothing!!! It wan't go in fullscreen!!
Any idea please?
thanks,
alberto
If the view you're presenting is full screen, this should obscure the tab bar. That said, you might need to re-size the view programmatically so that it's the same size as the UIWindow.
You should be able to do something along the lines of...
[nw setFrame:[[UIScreen mainScreen] applicationFrame]];
[nw setNeedsLayout];
...to achieve this. (Sorry, I'm on a Windows box at the moment, so I can't confirm this. Hopefully someone will provide any tweaks if required.)
You should then dismiss the initial modal view via a delegate method in the originating class. (See the "Dismissing a Modal View Controller" section of Apple's View Controller Programming Guide for iOS.) The originating class would then dispose of the modal view.
Resolved using notification!
When a tab change, i send a notification and close the modal controller.
- (BOOL)tabBarController:(UITabBarController *)tbController shouldSelectViewController:(UIViewController *)viewController {
[[NSNotificationCenter defaultCenter] postNotificationName:#"DataComplete" object:nil];
return YES;
}
In my view classes receive a notification and dismiss the controller!
- (void)downloadDataComplete:(NSNotification *)notif {
NSLog(#"Received Notification");
[self dismissModalViewControllerAnimated:YES];
}
Now it's possibile to reopen a modal view also changing tab!
This is a workaround but works!
alberto.