UIDocumentInterationController item option menu will not dismiss when click in the Navigation bar - navigationbar

Title: UIDocumentInteractionController dismissing the popup when clicking anywhere in the navigation bar.
My code works find. It works well in my iPhone and iPad simulator for the most part. It does what I want., however, my issue is dismissing the default popup menu. It goes away if I click in the view area, it goes away if I pick an option in the popup, and it also goes away if I click in the tab bar area. This is good. However if I click anywhere in the navigation bar it stays put. And if I click any of the items in the navigation bar it crashes. I would like the default popup to dismiss if I click in the navigation bar as well.
outputURLViewController.h
#import <UIKit/UIKit.h>
#interface outputURLViewController : UIViewController<UIDocumentInteractionControllerDelegate,UIPopoverControllerDelegate>
{
IBOutlet UIWebView *previewWebView;
}
#property (nonatomic, strong) NSString *outputURLString;
#property (nonatomic, strong) NSString *outputURLName;
#property (nonatomic, retain) UIWebView *previewWebView;
#property (nonatomic, strong) UIDocumentInteractionController *docController;
- (IBAction)actionButton:(id)sender;
#end
outputURLViewController.m
#import "outputURLViewController.h"
#interface outputURLViewController ()
{
NSArray *myButtonArray;
UIBarButtonItem *myActionButton;
}
#end
#implementation outputURLViewController
#synthesize outputURLString;
#synthesize outputURLName;
#synthesize previewWebView;
- (void)viewDidLoad
{
[super viewDidLoad];
//Creates my action put and put it in the right side of navigation bar
myActionButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(actionButton:)];
myButtonArray =[[NSArray alloc] initWithObjects:myActionButton, nil];
self.navigationItem.rightBarButtonItems = myButtonArray;
NSURL *url = [[NSBundle mainBundle] URLForResource:outputURLString withExtension:#"pdf" subdirectory:#""];
//displays my document in the webview
[previewWebView loadRequest:[NSURLRequest requestWithURL:url]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
//action that display my options in a default popup menu
- (IBAction)actionButton:(id)sender
{
NSURL *url = [[NSBundle mainBundle] URLForResource:outputURLString withExtension:#"pdf" subdirectory:#""];
if (url) {
self.docController = [UIDocumentInteractionController interactionControllerWithURL:url];
self.docController.delegate = self;
[self.docController presentOptionsMenuFromBarButtonItem:myActionButton animated:NO];
}
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application{}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application{}
//dismiss my popup menu in the view, but not the navigation bar when click
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller{}
#end
As you can see it very simple default popup menu code. It does what I want. I just trying to figure how to prevent it from crashing when a navigation item button is click before the popup is dismissed.
My Error that I get is:
Terminating app due to uncaught exception 'NSGenericException', reason: '-[UIPopoverController dealloc] reached while popover is still visible.'
My DocumentInteractionControllerDidDismissOptionsMenu: does work when I click in the view or any where else except the navigation bar. So is there away to prevent anyone from clicking another button in the navigation bar until the uidocumentinteractioncontroller is dismissed or have it dismiss when they tap in the navigation bar area? Or is this a normal bug that doesn't have a fix?

Decide to hide the navigation items when the popup is active.
I used this code in the myActionButton section
if ( IDIOM == IPAD ) {
self.navigationItem.rightBarButtonItem = nil;
self.navigationItem.hidesBackButton = YES;
}
and this code in my documentInteractionControllerDidDismissOptionsMenu
if ( IDIOM == IPAD ) {
self.navigationItem.rightBarButtonItem = myActionButton;
self.navigationItem.hidesBackButton = NO;
}

Related

Popover button not showing in split view app

I have a split view app that should show a menu button when the device is in portrait orientation and the Master view is hidden.
When the app launches in portrait mode, this function is executed:
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc {
barButtonItem.title = #"Menu";
self.popoverController = pc;
self.rootPopoverButtonItem = barButtonItem;
// Get current detail view (splitVC-->detailNavVC-->currentVC).
UINavigationController *detailNav = [self.splitController.viewControllers objectAtIndex: 1];
UIViewController <SubstitutableDetailViewController> *detailViewController = [detailNav.viewControllers objectAtIndex: 0];
[detailViewController showRootPopoverButtonItem: rootPopoverButtonItem];
}
This function in turn launches the function in TitleViewController.m:
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the toolbar.
NSMutableArray *itemsArray = [toolbar.items mutableCopy];
[itemsArray insertObject: barButtonItem atIndex: 0];
[toolbar setItems:itemsArray animated:NO];
}
All of this code seems to run correctly, but no menu button is showing. Any ideas? Thanks.
I seemed to have solved the problem by adding the following line after setting the toolbar items:
[self.view reloadInputViews];

Implementing a UISplitViewController Master Detail Application - UIPopOverController is null until rotation.

I am trying to implement a simple UISplitViewController where when in portrait mode the master view is hidden and appears with a button in a popover.
My AppDelegate is set up like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch.
self.splitViewController =[[UISplitViewController alloc]init];
self.rootViewController=[[RootViewController alloc]init];
self.detailViewController=[[FirstDetailViewController alloc]init];
UINavigationController *rootNav=[[UINavigationController alloc]initWithRootViewController:rootViewController];
UINavigationController *detailNav=[[UINavigationController alloc]initWithRootViewController:detailViewController];
self.splitViewController.viewControllers=[NSArray arrayWithObjects:rootNav,detailNav,nil];
self.splitViewController.delegate=self.detailViewController;
splitViewController.presentsWithGesture = NO;
// Add the split view controller's view to the window and display.
[self.window setRootViewController:self.splitViewController];
[window makeKeyAndVisible];
return YES;
}
in FirstDetailViewController I set up a button like this:
UIImage *buttonImage = [UIImage imageNamed:#"button-menu.png"];
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
[aButton addTarget:self action:#selector(showNavigation) forControlEvents:UIControlEventTouchUpInside];
aBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aButton];
self.appDelegate.rootPopoverButtonItem = aBarButtonItem;
showNavigation looks like this:
-(void)showNavigation{
NSLog(#"I am in show navigation and pc=%#",self.popoverController);
[self.popoverController presentPopoverFromRect:self.view.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
When I initially load the app and press the button I get an NSLog of
I am in show navigation and pc=(null)
And the pop over dosen't show. Now when I rotate the device to landscape mode, and then back to portrait, the master view hides and shows as expected, and the button now works in portrait mode.
Here is the code that handles the rotation:
- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {
[[self navigationItem] setLeftBarButtonItem:aBarButtonItem];
[self setPopoverController:pc];
self.appDelegate.rootPopoverButtonItem = aBarButtonItem;
}
// Called when the view is shown again in the split view, invalidating the button and popover controller.
- (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
[[self navigationItem] setLeftBarButtonItem:nil];
[self setPopoverController:nil];
self.appDelegate.rootPopoverButtonItem = aBarButtonItem;
}
How do I get the popovercontroller to not be null before any rotation occurs?
Ok turns out I had an if in my willHideViewController which did not include the [self setPopoverController:pc]; line. duh!

Using ImagePickerController to get photo from library ok but navigating away then back to same view the image is gone

I am trying to build a view where a user can select an image and it is retained within that view after navigating away from the view and coming back again. As a simple test app, I have created two view controllers. The first view controller has a forward button and uses a modal segue to go to the second view controller. The second view controller has a back button (modal segue back to first view controller) a Choose button and a Image button. So far I have configured the choose button to use the imagepickercontroller to select an image from the library and display onto the button which works no problem. The issue is that when i press the back button and the forward again back to the same screen the image isn't retained i have to reselect it. The intention is for the user to be able to take a picture or video of themselves performing an action and then select it within this app and have the picture displayed there for future reference.
My coding is as follows:
ViewController.h
#interface ViewController : UIViewController
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
IBOutlet UIButton *selectFromPhotoLibraryButton;
IBOutlet UIButton *displayPictureButton;
}
#property (nonatomic, retain) UIButton *selectFromPhotoLibraryButton;
#property (nonatomic, retain) UIButton *displayPictureButton;
- (IBAction)selectPicture;
#end
ViewController.m
#implementation ViewController
#synthesize selectFromPhotoLibraryButton;
#synthesize displayPictureButton;
-(IBAction)selectPicture
{
if([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypePhotoLibrary])
{
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:picker animated:YES];
[picker release];
}
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info
{
UIImage *image = [[info objectForKey:UIImagePickerControllerOriginalImage] retain];
[displayPictureButton setImage:image forState:UIControlStateNormal];
[self dismissModalViewControllerAnimated:YES];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *) picker
{
[picker dismissModalViewControllerAnimated:YES];
}
Please let me know if you require any of the other bits of code (its only the default app stuff, no further modification).
As looking to your problem
I think you have to store selected image in NSUserDefault as archived data or something like that.
When u come back to second view then check first in NSUserDefault for image is saved or not.
If u got it then assign it to UIImage object by unarchiving.
As I have not implemented it so can't be sure.
I've just set something like this up myself, I have the chosen image immediately placed in a UIImageView.
First, set up your view controller as a UIImagePickerDelegate:
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
Then wherever you want to init the UIImagePicker, alloc, init and set its delegate to self:
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setDelegate:self];
[self presentViewController:imagePicker animated:YES completion:nil];
And then I have the image picker storing the UIImage into the ImageView and also into the NSUserDefaults.
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info {
UIImage *image = [[info objectForKey:UIImagePickerControllerOriginalImage] retain];
[userDefaults setObject:image forKey:#"image"];
[userDefaults synchronize];
[self dismissViewControllerAnimated:YES completion:^{
[self updatePreviewImage:image];
}];
}
- (void) imagePickerControllerDidCancel:(UIImagePickerController *) picker {
[self dismissViewControllerAnimated:YES completion:nil];
}
I hope this works for you, and anyone else that view this post.

Image instead of title in navigation bar of TTLauncherView

I use the TTLauncherView in my project. To have a custom navigation bar background I have subclassed the UINavigationBar in my app delegate. This works fine and all navigation bar's now have this custom style.
#implementation UINavigationBar (CustomNavBarBG)
-(void)drawRect:(CGRect)rect{
UIImage *image = [UIImage imageNamed:#"navbar_s.png"];
[image drawInRect:self.bounds];
}
#end
When navigating through the views the title appears in the middle of the bar. But on the navigation bar of the main screen, the launcher, I want to have an image instead of the title. Is this possible?
How to implement it?
you can override the default title view when you load your controller with a custom UIView, such as a UIButton:
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *logoView = [[[UIButton alloc] initWithFrame:CGRectMake(0,0,85,40)] autorelease];
[logoView setBackgroundImage:[UIImage imageNamed:#"navBarLogo.png"] forState:UIControlStateNormal];
[logoView setUserInteractionEnabled:NO];
self.navigationItem.titleView = logoView;
}
I'm actually not sure why I used UIButton here :-) maybe you can use a UIImageView instead, but this code works fine.

cannot close RootViewController

In Xcode 4 I've created a SplitView project, so I have a DetailViewController and a RootViewController.
In RootViewController's viewDidLoad(), I have added a cancel button on the left side like this
// add a cancel button on the left side
cancelButton = [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self action:#selector(cancelAction:)] autorelease];
self.navigationItem.leftBarButtonItem = cancelButton;
When the RootViewController is displayed and I click on the cancel button, I want to close the RootViewController. In my cancelButton handler I've tried calling
#if 0
[self dismissModalViewControllerAnimated:YES];
#else
[self.navigationController popViewControllerAnimated:YES];
#endif
but neither one of them work for me. I've tried googling for hours but have still not found a solution.
Can someone please tell me how to close the RootViewController?
thanks for your help
I'm assuming you're trying to close popover of RootViewController in portrait orientation because in landscape it doesn't make sense.
You can do it like this:
1) cancel button handler:
-(void)cancelAction {
[self.detailViewController.popoverController dismissPopoverAnimated:YES];
}
2) popoverController is private in detailViewController so you must make it public (or add method to detailview that will have access to popoverController property and call this method from cancelAction in RootViewController):
2.1) delete
#property (nonatomic, retain) UIPopoverController *popoverController;
from
#interface DetailViewController ()
...
#end
2.2) add
#property (nonatomic, retain) UIPopoverController *popoverController;
inside
#interface DetailViewController : UIViewController

Resources