I am seeing a very weird UI bug with the ABPeoplePickerNavigationController on iPad (in landscape) where when a user clicks the search bar in the PeoplePicker then subsequently cancels out, the keyboard is not resigned and the UI of the people picker gets all messed up. Here is a photo of the bug:
The ABPeoplePickerNavigationController is presented in a modal form sheet using the following code:
- (void) openAddressBook
{
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
picker.delegate = self;
[picker setModalPresentationStyle: UIModalPresentationFormSheet];
[self presentViewController:picker animated:YES completion: nil];
}
The UI is as expected until a user taps on the search field, which brings up the keyboard, then cancels out of the search field, which does not resign the keyboard as it does on iPhone. Also, when the user scrolls the contacts list in this mode, all of the letter headers (i.e. the A header) are pinned where the A header is currently, not at the top of the view directly under the search bar.
Is there a reason that the keybaord is not being resigned here?
I am having difficulty debugging this as the ABPeoplePickerNavigationController is not subclassable, so any help would be greatly appreciated!
That is how UIModalPresentationFormSheet works: by default, it does not dismiss the keyboard when first responder is resigned. Clearly ABPeoplePickerNavigationController is not expecting to be used this way. My suggestion: don't do that. Use a popover or a normal presented view. (My experience is that a popover looks better.)
use [self.view endEditing:YES]; when you are done
Related
I have an iPad app where a UIWebView is loading a html page which consists of n number of phone numbers within a href tag.
And on tap of these phone numbers iOS default contextual menu like a popover-controller is getting displayed with 3 default options like --- Send Message, Add to Contacts and Copy.
At certain point of time I’m just popping all the UIViewController to rootViewController, so when this action is getting performed if this contextual menu is displayed on screen then it is not at all getting dismissed even when the view comes to rootViewController from the view which consists the UIWebView with phone numbers. I guess this is because the contextual menu is getting displayed from UIWindow(like UIAlertView).
I want to dismiss or hide this contextual menu at this point programmatically.
I have tried to achieve this by below attempts,
1) On viewDidDisappear,
[UIMenuController sharedMenuController].menuVisible = NO;
2)I tried by fast enumeration like below,
for (UIView *subView in view.subviews){
if ([subView isKindOfClass:[UIPopoverController class]]) {
[(UIPopoverController *)subViews dismissPopoverAnimated:YES];
}
}
//similiarly I tried by checking for UIMenuController as well
None of the above attempts was successful in achieving this.
Can any one let me know how can I dismiss contextual menu of UIWebView programmatically?
Any help is appreciated in advance.
Before popping to the root view controller you can use
Objective-C:
[self dismissViewControllerAnimated:NO completion:nil];
Swift:
self.dismissViewControllerAnimated(false, completion: nil)
to get rid of the contextual menu.
I am trying to present a view controller (say photoEditedViewController) on top of AFPhotoEditorController as,
- (void)photoEditor:(AFPhotoEditorController *)editor finishedWithImage:(UIImage *)image{
PhotoEditedViewController* vc = [[PhotoEditedViewController alloc] initWithNibName:#"PhotoEditedViewController" bundle:nil];
[editor presentViewController:vc animated:YES completion:nil];
}
Then in PhotoEditedViewController.m
- (IBAction)cancel {
[self dismissViewControllerAnimated:YES completion:nil];
}
Once I am back to AFPhotoEditorController, the top navigation bar is unresponsive at all. I am unable to tap on any of the top navigation buttons.
I am not sure if I am doing anything wrong here. Any help would be appreciated.
I am the iOS Lead at Aviary. Once the user has finished in the editor by pressing the done or cancel buttons, the user will not able able to interact with any of the elements of the editor. This is because once the edit has been finished by the user, the SDK will begin performing any high-resolution edits that have been requested by the developer. You should dismiss the editor before presenting your new controller.
My ipad project is master-detail view based. There is a button on detail view's toolbar, when user tap on the button, it popup a popover view to show four buttons (as menu). Three of buttons' actions are like the following (the three buttons show three different model form sheets):
- (void) showOnlineSgf
{
NSLog(#"showOnlineSgf");
TGOOnlineSgfViewController *dlg =
[[TGOOnlineSgfViewController alloc] initWithNibName:#"TGOOnlineSgfViewController"
bundle:nil];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:dlg];
[nav setModalPresentationStyle:UIModalPresentationFormSheet];
[self presentViewController:nav animated:YES completion:nil];
dlg = nil;
nav = nil;
}
The other button's action is to show a MFMailComposeViewController. Code is like the following:
- (void) emailCurrentGame
{
NSLog(#"email current game");
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[self presentModalViewController:picker animated:YES];
picker = nil;
}
The weird behavior is that when I tap the button what should execute showOnlineSgf(), but emailCurrentGame() is actually executed. When I set a breakpoint in showOnlineSgf(), it's hit, and step by step, each statement in showOnlineSgf() is executed. But the result on screen is a MFMainComposeViewController shows up.
I know this question is hard to answer. Any idea is appreciated.
Check your outlet connection of your UIButton that triggers showOnlineSgf. Most likely you copy pasted your UIButton in Interface Builder, which causes it to copy its assigned action as well. Then you've connected your other action, resulting in your UIButton having two actions.
To resolve the problem, simply disconnect your UIButton that triggers showOnlineSgf from the emailCurrentGame action.
Sounds like you copy pasted in the interface builder an already connected button. Check if the button has more than one action assigned.
Got a strange problem. The cancel button that normally is shown at the navigation bar when you add a UIImagePickerController is missing when I add it to my UIPopoverController.
I have tried to subclass the UIImagePickerController and add a navigation button to the navigation bar myself, but it did not show up.
If I select my camera roll the back button gets automatically added, but the cancel button is still missing.
Anyone know what could cause this?
Here is the code i use. Note that _popOver is the instance of my UIPopoverController.
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[_popOver setContentViewController:picker animated:YES];
I have tried this code and now I think it's a default behavior. UIImagePickerController usually presented as modal view controller and the aim of Cancel button is to dismiss it. When you put UIImagePickerController into UIPopoverController then Cancel button became meaningless. For dismissing this you can just tap anywhere (except UIPopoverController view). If you want to access UIImagePickerController when UIPopoverController will/did dismissed use UIPopoverControllerDelegate method:
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
UIImagePickerController *imagePicker = (UIImagePickerController*)popoverController.contentViewController;
return YES;
}
I am trying to display a modal viewController in an iPad app using the UIModalPresentationFormSheet view style. I am looking to produce something similar to the Mail app's new message UI/animation.
There are two things that are not behaving correctly:
The modal viewController that is presented always animates to y=0, i.e. to the very top of the
view and not some pixels below the status bar as it does in the mail app.
The documentation says:
UIModalPresentationFormSheet The width
and height of the presented view are
smaller than those of the screen and
the view is centered on the screen. If
the device is in a landscape
orientation and the keyboard is
visible, the position of the view is
adjusted upward so that the view
remains visible. All uncovered areas
are dimmed to prevent the user from
interacting with them.
However, in my case there is no dimming and I can still interact with the parentView below the modalViewController.
The controller that presents the modalView I do this:
AddNewItemViewController *newItemViewController = [[AddNewItemViewController alloc] initWithNibName:#"AddNewItemViewController" bundle:nil];
[self presentModalViewController:newItemViewController animated:YES];
[newItemViewController release];
In the viewController being presented I do this:
- (void)viewDidLoad {
[nameField becomeFirstResponder];
[self setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self setModalPresentationStyle:UIModalPresentationFormSheet];
[super viewDidLoad];
}
I hope someone can help me out.
Is there some other properties I need to set on the parent and modalViewController?
Is the viewDidLoad not the right place to do this setup?
Thanks in advance:)
You set the transition and presentation styles when you create the modal view, before you call presentModalViewController. Remember, the view that creates the modal view 'owns' that object. You want the owner to set these properties because you might implement this modal view elsewhere in the app and want different transition or presentation styles. This way, you set it each time as appropriate.
AddNewItemViewController *newItemViewController = [[AddNewItemViewController alloc] initWithNibName:#"AddNewItemViewController" bundle:nil];
newItemViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:newItemViewController animated:YES];
[newItemViewController release];
You're right in calling becomeFirstResponder in viewDidLoad.