don't want to dismiss UIPopover - objective-c

i am using this following code to display a popover in my View
imagePopOver = [[UIPopoverController alloc];
initWithContentViewController:self.photoLibraryImageCollection.imagePickerController];
imagePopOver.popoverContentSize = CGSizeMake(185,675);
imagePopOver.delegate = self;
[imagePopOver presentPopoverFromRect:CGRectMake(600,0, 140, 800)
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
it working fine however if we click any other part of myView ,this displayed popover is dismissing.can any one tell me how can i avoid this problem. i don't want to dismiss it at any time.can any one tell me how can do it.

In the popover's delegate (your viewController, probably), implement
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController {
return NO;
}
Don't forget to set the delegate!

just wrote the below code at the time of popover initialization.
myPopOver.passthroughViews = [NSArray arrayWithObject:self.view];
in the above code will not dismiss your popOver and we can work with our View.
if you don't want to dismiss UIpopover only at the time of a textBox edit,simply write
myPopOver.passthroughViews = [NSArray arrayWithObject:self.textBox];

Related

Pop controller after back bar button is pressed

I have a UINavigationController ans a chain of 3 simple controllers. Each one has a button. When press a button a next controller is Pushed. ViewController1 -> ViewController2 -> ViewController3. When I push a back button on the 3rd view i want to move to the first view. Using of backBarButtonItem is obligatory. Here is the code for second controller:
#import "ViewController2.h"
static BOOL isBackButtonPressed;
#implementation ViewController2
- (void)viewDidLoad {
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"back from 3" style:UIBarButtonItemStyleBordered target:nil action:nil];
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
if (isBackButtonPressed) {
[self.navigationController popViewControllerAnimated:YES];
} else {
isBackButtonPressed = YES;
}
[super viewWillAppear:animated];
}
#end
But when I press back button on the third view I return to the second view instead of the first view. Could you help me to return to the first view pressing back button on the third view.
I tried suggestions from answers but they don't help.
Adding a selector to backBarButtonItem doesn't help because it is never called.
Adding a [self.navigationController popToRootViewControllerAnimated:YES] in viewWillDisappear methos also doesn't work. I don't know why. I think that the actual problem is how backBarButtonItem works.
Any other suggestions?
The behaviour I try to achieve exists in the calendar on iPhone. When you rotate iPhone to landscape you get to the weeek view. Then go to the event details, and rotate to the portrait. When you press back button you will get to a day view not to a week view, so a controller with weekview is skipped.
After countless number of tries my solution was simply not use backBarButtonItem! As whatever i do it always goes to previous viewController instead of calling its selector
Instead I use only leftBarButtonItem for navigation, as it guarantees calling my action.
Here an example
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 27, 22)];
[backButton setImage:[UIImage imageNamed:#"backbutton"] forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
This certainly calls backButtonPressed action.. This works both for IOS 6 and 7
No need to register a new selector for the back button, just do:
-(void)viewWillDisappear{
if ( [self.navigationController.viewControllers containsObject:self] )
//It means that the view controller was popped (back button pressed or whatever)
//so we'll just pop one more view controller
[self.navigationController popViewControllerAnimated:NO];
}
in your ViewController3 viewWillDisappear method
Try using this in your third view controller, this way you check if you have pressed the back button and directly pop to the root view controller which as you stated is your first view controller.
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
[self.navigationController popToRootViewControllerAnimated:YES];
}
[super viewWillDisappear:animated];
}
I had the same problem as you beofre and fixed it like this:
You can capture the back button on the ViewController3 and before poping the view, remove ViewController2 from the navigation stack like this:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"back from 3" style:UIBarButtonItemStyleBordered target:self action:#selector(customBackPressed:)];
}
-(void)customBackPressed:(id)sender {
NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray: navigationController.viewControllers];
for (UIViewController *vc in viewControllers)
{
// If vc is ViewController2 type, remove it
}
navigationController.viewControllers = allViewControllers;
[self.navigationController popViewControllerAnimated:YES];
}
Because ViewController2 is not in the stack anymore, it will jump to ViewController1.
Also, if ViewController1 is the root view controller, you can just do:
[self.navigationController popToRootViewControllerAnimated:YES];

UINavigationBar, back button, and dismissModalViewController

I have an app that is navigation based, so all views default to have a top nav bar. I have reached a page where a back button is not displayed by default for whatever reason and I was required to add one programatically. Unfortunately, the back button does not dismiss the modal view as expected.
I load the view in question through:
-(IBAction) linkPress:(id)sender
{
potentialUrl = [[NSURL alloc] initWithString:((Button*)sender).emailContent];
webViewInst = [[WebView alloc] initWithNibName:#"WebView" bundle:nil url:potentialUrl];
NSString *deviceType = [UIDevice currentDevice].model;
if([deviceType isEqualToString:#"iPad"] || [deviceType isEqualToString:#"iPad Simulator"]){
[self presentModalViewController:webViewInst animated:YES];
}
else {
[self.navigationController pushViewController:webViewInst animated:YES];
}
}
I add the back button through:
UIBarButtonItem *MKbackBtn = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButton:)];
[self.navigationItem setLeftBarButtonItem:MKbackBtn];
And the action that the back button should take to remove the view and return to the previous view:
-(IBAction)backButton:(id)sender
{
UIViewController* parent = [self parentViewController];
if(parent==nil) {
parent = [self presentingViewController];
}
[parent dismissModalViewControllerAnimated:YES];
}
If another set of eyes could go over these bits of code and try to discern what mistake I have made, that would be greatly appreciated! I am more than willing to provide more information/code as well.
Thanks!
You're calling dismissModalViewControllerAnimated but based on your code above there's a chance that it's not presented as modal and is instead pushed onto the navStack, in which case dismissModalViewControllerAnimated wouldn't actually dismiss it. Instead you would need to do popViewController etc. You should be casing around the presentation means. Can you confirm that this isn't part of the problem?
Also, off the top of my head I think you would call [self dismissModalViewController...] rather than parent.
Displaying a view controller modally does not include it in the navigation controller's stack. You have to provide your own UI mechanism to dismiss the modal view. It looks to me like your solution to dismiss the modal view controller should mostly work--although I think all you need is this one line in backButton::
[self dismissModalViewControllerAnimated:YES];

xcode adding buttons to navigation bar

I am making a simple app to display drink details, and now I am trying to add a view that allows the user to input their own drink. I already created a view to display the details, and now I am just passing the view into another controller to make the add drink view. Problem is, when I try to add a "cancel" and "save" button, it doesn't appear, although the code complies without any errors. I have attached code as reference.
This is the code that makes the new view, when the add button is pressed. (I made an add button that works, and it pulls up the nav bar)
- (IBAction)addButtonPressed:(id)sender {
AddDrinkViewController *addViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailSecond"];
UINavigationController *addNavController = [[UINavigationController alloc] initWithRootViewController:addViewController];
[self presentModalViewController:addNavController animated:YES];
NSLog(#"Add button pressed!");
This is the code from the addviewcontroller implementation file:
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancel:)];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:#selector(save:)];
}
- (IBAction)save:(id)sender {
NSLog(#"Save Pressed");
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)cancel:(id)sender{
NSLog(#"Cancel Pressed");
[self dismissModalViewControllerAnimated:YES];
}
I have imported the header from the addview into the root controller, so I don't think that is the problem, do any of you guys see anything that's wrong?
Just change the line
[self presentModalViewController:addNavController animated:YES];
to
[self presentViewController:navigationController animated:YES completion:nil];
and see the magic. I also tested the code
My advice to you is to create a template for the view before you run through any code in the XIB file of your app. Rather than trying to set each button after allocating a brand new view, setting a new one in the XIB before-hand allows you to link each element with the app and make sure it looks just right before you debug.
Simply go into your "[Your-App-Name]viewController.xib" and drag a view from the objects library to the pane on the left. From here add each of your elements and position them where you want on the view. Now in the "[Your-App-Name]viewController.h" file, add IBOutlets for each element that you need to change, and add IBActions for each of the buttons. Also create an IBOutlet for the new view.
IBOutlet UIView* addDrinkView;
Back in the XIB file, use files owner to link each outlet to each element and each method to each button. Make sure you link the IBOutlet
Now in your "[Your-App-Name]viewController.m" file, you can define each button method and all you need to do to access the new view and dismiss it are the following:
-(IBAction)openAddView
{
[self setView:addDrinkView];
}
-(IBAction)saveButtonPressed
{
[self setView:view];
//save code goes here
}
-(IBAction)cancelButtonPressed
{
[self setView:view];
//cancel code goes here
}
This should be much easier than trying to position everything in code.
Hope this helps!

Fullscreen iPad UIPopoverController

I have an iPad app which displays a UIImagePicker through a UIPopoverController.
I would like to make the popovercontroller fullscreen (or at least as big as possible).
I'm using the presentPopoverFromRect method with a new CGRect which I have set to various widths and heights with no result. The source of the imagepicker is UIImagePickerControllerSourceTypePhotoLibrary.
UIPopoverController* popoverController = [[UIPopoverController alloc] initWithContentViewController:photoPicker];
popoverController.delegate = self;
popoverController presentPopoverFromRect:CGRectMake(0, 0, 2500, 2500) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Can I even make this fullscreen? What about sourcetype UIImagePickerControllerSourceTypeCamera?
To set popover size you can override -contentSizeForViewInPopover in viewcontroller which is
placed in popovercontroller.
presentPopoverFromRect is used for defining frame from which popover will be opened, not for setting it's size.
I just verified that this code works on an iPad 1 and iPad 4 (meaning it is supported in iOS 5.1.1 - 6.1.2)
popover = [[UIPopoverController alloc] initWithContentViewController:yourVC];
[popover setPopoverContentSize:CGSizeMake(1024, 1024)];
[popover presentPopoverFromRect:CGRectZero
inView:appDelegate.splitViewController.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
You should note that it's difficult to dismiss the popover since it will "fill the screen" in portrait or landscape. I do have these methods in my appDelegate.splitViewController:
- (BOOL)shouldAutomaticallyForwardRotationMethods {
NSLog(#"MG - shouldAutomaticallyForwardRotationMethods");
return YES;
}
- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
NSLog(#"MG - automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers");
return YES;
}
Just unhide/hide a button in a corner of yourVC to dismiss with this:
[popover dismissPopoverAnimated:YES];
It should also be noted that "popover" is a strong property, or you will get a deallocated message when it tries to present.
You might also want a ModalViewController instead? This one has 4 different presentationstyles (one of them fullscreen)
A good example is the prototype written in this question: presentModalViewController fullscreenmode issue
(it's in the //---EDIT---//)
Check it out if it's something for you.

display popover when user click into text field?

Hi i have been following a book a how to display the popover when the user clicks on a toolbar button item. It works fine but I want to display the popover when user clicks into a textField. It seems like it would be some minor adjustment. Like changing the IBAction
"showPopover" method a bit. This is what the code looks like for that method:
- (IBAction)showPopover:(id)sender{
if(popoverController == nil){ //make sure popover isn't displayed more than once in the view
popoverController = [[UIPopoverController alloc]initWithContentViewController:popoverDetailContent];
[popoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
popoverController.delegate = self;
}
}
There is a another instance method other than "presentPopoverFromBarItem" that is called
"presentPopoverFromRect".Would I use that instead? I tried to write the code for it but I'm not sure how to relate it to my TextField or how draw the rectangle needed.Can anyone help me with this?Thanks.
you have to use the textfields delegate method textViewShouldBeginEditing:
Something like this:
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
if(popoverController == nil){ //make sure popover isn't displayed more than once in the view
popoverController = [[UIPopoverController alloc]initWithContentViewController:popoverDetailContent];
}
[popoverController presentPopoverFromRect:textView.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
popoverController.delegate = self;
return NO; // tells the textfield not to start its own editing process (ie show the keyboard)
}
For those who want to display a popover, but do not want to display the keyboard when the text field is tapped, here is the solution that I've always used (Notice this is different than the previous answers textFieldShouldBeginEditing):
/*
* Handle when text field is about to start edit mode
*/
- (BOOL)textFieldShouldBeginEditing:(UITextField *) textField
{
// Create popover controller if nil
[self.myPopover presentPopoverFromRect:textField.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
return NO;
}
Hope this helps!
if your textField is inside a table cell your popover will point to the top of the screen because the frame of the textField frame is in reference to the view that contains the textfield. So you need to give it the correct view reference. You need to use the textField.superview as your view reference.
- (BOOL)textFieldShouldBeginEditing:(UITextField *) textField
{
...
[self.myPopover presentPopoverFromRect:textField.frame inView:textField.superview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
return NO;
}
Yes, there is a presentPopoverFromRect method.
To wire it up to the UITextField, you will need to implement the UITextFieldDelegate and call your showPopover code from the textFieldDidBeginEditing method.
The rect you use should be the rect of the TextField.