Hide UIActionSheet on iPad - ipad

I just got a mail from apple that my iPad app was rejected because my 'app contains popover elements that didn't point to the element that revealed them and more than one popover element visible onscreen at a time'.
The problem is that I call an actionsheet which is still visible when I switch from one view to another and that there can be called to actionsheets at a time.
Now I ask myself how I can hide an actionsheet on a view change or when another actionsheet is opend.

I solved the issue with the sheet showing multiple times when you tap the same button by checking isVisible, as in the following:
- (IBAction) btnFoo: (id) sender
{
if ([self.sheet isVisible]) {
[self.sheet dismissWithClickedButtonIndex:self.sheet.cancelButtonIndex animated:YES];
return;
}
[self.sheet showFromBarButtonItem:sender animated:YES];
}
Hope that helps.

Related

How to dismiss contextual menu of UIWebView programmatically?

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.

UIAlertView send storyboard back to start

iPhone app with a storyboard setup. Button on the initial view that links through to another view. I have added an alert to that button click so that when it is tapped the view changes and immediately the alert appears asking 'Do you want to continue? Yes No'
If they click yes the alert disappears, if they click no the storyboard should go back to the start.
This is what I've got so far and it doesn't work, nothing happens. I've tried multiple various solutions touted on SO but nothing is working so far. Removing the buttonindex check doesn't do anything.
I'd actually prefer this alert to appear even before the view changes but at the moment I have it displaying after the segue occurs which isn't ideal but if I could get it to segue back it would still be acceptable.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex==1) {
[self.navigationController popViewControllerAnimated:YES];
}
}
any ideas?
I'm guessing you've linked the button on your first view to the second view using a segue on the storyboard. To get it so that the UIAlertView pops up on the first view and then the segue is triggered depending on whether Yes or No is clicked you'll need to delete that segue and instead create it again by Ctrl-dragging from the first view (not the button) to the second view.
Create an IBAction for your button (if you haven't already) by Ctrl-dragging from your button to the views .h file and selecting Action. This should automatically create the method in the .m file - in that method you'll need to call your UIAlertView.
- (IBAction)buttonPressed:(id)sender
{
[myAlertView show];
}
Then the clickedButtonAtIndexMethod should be similar to what you had before. Instead of popping a controller (because the segue hasn't automatically happened) you'll want to call your segue using performSegueWithIdentifier.
- (void)alertView (UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// They clicked Yes
if (buttonIndex==1)
{
[self performSegueWithIdentifier:#"YourSegueName" sender:self];
}
}
In regards to the clickedButtonAtIndex method not being called have you made the view a delegate of UIAlertView? So in your views .h file you need to have UIAlertViewDelegate like this:
#interface MyViewController : UIViewController <UIAlertViewDelegate>

Navigation controllers toolbar goes blank after showing a UIActionSheet from it

In an iOS run on iOS 6.1 (emulated) and 6.1.3 (physical device) application we show an UIActionSheet from a view with the following code:
UIActionSheet *actionCreateNewComment = [[UIActionSheet alloc] initWithTitle:CLocalised(#"EditExistingComment") delegate:self cancelButtonTitle:CLocalised(#"No") destructiveButtonTitle:nil otherButtonTitles: CLocalised(#"Yes"), nil];
[actionCreateNewComment setActionSheetStyle:UIActionSheetStyleBlackOpaque];
[actionCreateNewComment setTag:ActionSheetTagNewComment];
[actionCreateNewComment showFromToolbar:self.navigationController.toolbar];
[actionCreateNewComment release];
The View sets the toolbar with:
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:control];
[self setToolbarItems:[NSArray arrayWithObject:item]];
Where control is an UISegmentedControl.
The code for handling the button actions are:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
bool shouldAddNewComment = buttonIndex == [actionSheet cancelButtonIndex];
[self navigateToCommentScreen:shouldAddNewComment];
}
Every time this action sheet is shown the tool bar will go "blank". Not only for this view but also for the other views.
Here is an example of a work flow:
Note that if I navigate from Instr to Comment without the UIActionSheet, but otherwise the same code, the problem will not appear.
The problem here is that in the "Instr" view the toolbar is empty.
If I pop two more views to return to "List" its toolbar will be empty as well:
Even if I then navigate back to WO and Instr, by allocing and init new forms, and then pushing them, the toolbars will still be empty.
There is another navigation option from the "List" View that shows a "Summary" view. Depending on the data this view will show with or without buttons in the toolbar:
Both "Summary Button" and "Summary empty" are intended views. "Summary hidden" is shown after the UIActionSheet have been shown before navigating between Inst and Comment.
But if I navigate to a "Summary" view that is shown as "Summary Empty" in the picture (intended, due to the data) then the toolbar will start working everywhere again. Or at least until I show the UIActionSheet from the Instr view again.
There are some, in my opinion, strange things about this:
If I navigate to a view where the toolbar is empty, which hides the toolbar, see pic: "SummaryEmpty", then the toolbar will show as intended in the other views.
We use the same code to show an action sheet in other views of the application without any problem
If I run the application on an emulated iOS 5.1 or emulated iOS 5.0 the problem does not appear
Have I missed something when it comes to dismissing the action sheet or how to show it?
Please let me know if you want more information.
Update:
If I forcibly call [self setToolbarItems:nil] after the action sheet button event and then update it with the same items as before the Tool bar will show up as intended.
This does not feel as the right way to do it.
Update 2013-05-28:
Thanks to #LOP_Luke I found out that if I do not navigate to the "Comment" view from -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex but just returned the tool bar will start working again.
So, can there be some kind of problem when I navigate to another view when then clickedButtonAtIndex is still on the call stack?
Update 2013-05-29:
If I add a method:
-(void)commentScreenYes{
[self vanigateToCommentScreen:YES];
}
And change the button code to:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
bool shouldAddNewComment = buttonIndex == [actionSheet cancelButtonIndex];
if(shouldAddNewComment){
[self performSelectorOnMainThread:#selector(commentScreenYes) withObject:nil waitUntilDone:NO];
return;
}
[self navigateToCommentScreen:shouldAddNewComment];
}
Then it will work for the cancel button, but not for the yes button. The cancel button will also make the toolbar work again after it have been "broken" by the yes button. If I pipe both buttons through this flow (by adding a new method) they will both work.
And still, if I run it at iOs 5.1 it will work no matter which flow I choose.
The – setToolbarItems method is a UIViewController method specific to each child view controller of your navigation controller. Assuming [self navigateToCommentScreen:shouldAddNewComment] pushes a new view controller onto the navigation stack you will have to set the toolbar items for the new view controller too as a separate call, regardless of what the action sheet is doing. For example,
-(void) navigateToCommentScreen:(bool) shouldAddComment{
CommentViewController* viewController = [[CommentViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
[viewController setToolbarItems:self.toolbarItems];
}
Otherwise the new view controller will have no toolbar items and the toolbar will be blank.
Edit
I created a navigation controller with a root view controller that has a toolbar with a UISegmented control. I pushed a new view controller onto the navigation stack via a UIActionSheet delegate method and then popped it back. The toolbar was exactly how it should be on the root view controller (the segmented control faded back in as expected). You must be doing something more complicated with your controller with regards to setting the toolbar items that is causing them to disappear. Without seeing your viewController's source methods it's hard to tell what the problem is. Make sure that you are not setting your toolbar items to nil or resetting them with an empty array somehow.

Dismissing Keyboard FirstResponder problems

So i am making an app and am having some problems with dismissing the keyboard from UISearchBar and UITextFields. Here is the structure of my app:
NavigationController -> ViewC1 - (Modally)-> ViewC2 -(Modally) -> ViewC3
I have a search box in ViewC1, and when the "Search" button on the keyboard is pressed the keyboard is dismissed, this works fine. However if i return to ViewC1 after being in ViewC3 the keyboard no longer dismisses when the "Search" button is pressed. In the search bar delegate method i have put as follows:
- (void) searchBarSearchButtonClicked:(UISearchBar *)search
{
if ([search isFirstResponder]) {
[search resignFirstResponder];
} else {
[search becomeFirstResponder];
[search resignFirstResponder];
}
}
This does not solve the problem and i am not sure why the keyboard is not dismissing. For reference, when returning to the original ViewC1, ViewC3 is dismissed as follows:
UIViewController *parent = self.presentingViewController;
[parent.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Any help is appreciated, thanks.
Okay i figured out what the problem was. They first responder was being resigned but the keyboard was not disappearing because of a focus issue. There is a default behaviour on modal views to not dismiss the keyboard (which is not a bug apparently). So after returning from the modal view it was still having this behaviour (resigning first responder but not dismissing keyboard). The way i solved this was by placing the following code in both the modal views .m files:
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
This solved it for me. Then by either using:
[search resignFirstResponder];
or
[self.view endEditing: YES];
The keyboard will dismiss fine!
You'll need to do some debugging with break points to figure out why that conditional statement is not being hit. You could also use the endEditing method in UIView to simply resign the responder whenever search is clicked:
- (void) searchBarSearchButtonClicked:(UISearchBar *)search
[search endEditing:YES];
}
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIView_Class/UIView/UIView.html
Try it....
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[mySearchBar resignFirstResponder];
}
Please declare IBOutlet UISearchBar *mySearchBar; in your .h file
Set delegate in your .xib file.
Hope this helped
(A year later..)
I've just had the same problem with my iPad app.
I had a"Please register" UIView containing a few UITextFields which I would pop onto the screen. When the user tapped on a Close button, it'd disappear, and I'd use removeFromParentViewController to get rid of it.
[self.pleaseRegisterDlg removeFromParentViewController];
Now, when I ran this code on a real device in debugging mode from XCode, the story ended there. It all worked fine. But when I built an In-House app with this code, it behaved differently.
I would find that sometimes, no matter how many resignFirstResponders or disablesAutomaticKeyboardDismissals I put into the code, there would be times when the onscreen keyboard would suddenly appear, and refuse to go away programatically.
It made no sense, as the rest of my app didn't have any UITextFields... there was no reason for the app to display a keyboard.
My solution was to set the "Please Register" UIView to nil after removing it from the parent view.
[self.pleaseRegisterDlg removeFromParentViewController];
pleaseRegisterDlg = nil;
Apparently, having a UIView which isn't actually attached to any other UIViews but which contains UITextFields is sometimes enough to confuse iOS, and make the onscreen keyboard appear.
(Sigh. This one line of code wasted a few hours of my afternoon.. lesson learned !)

iOS - Create an Popover View using StoryBoard

Hi there, Now I'm trying to create a Pop-OverView using an Xcode
storyboard. Firstly, I have
rootViewController, UIViewController, and UITableViewController
I want the UIView to act as a page flip and the UITableView will show popOver under the navigationBar item controller.
For the UITableView, I want to make a Pop-Over under NavigationBar controller. The problem is, when I touch the Navigation item to show the UITableViewController, it shows correctly, but when I try to close the Pop-Over View, it won't close. And then, the navigation item doesn't work well. It shows multiple instances of popOverView when I touch it multiple times.
This doesn't seem to make sense to me. Can anyone help me out or tell me where to find documentation / tutorials on this?
UPDATE:
For the UIPopOverController, it seems to work well now, but it is still bugging me when I touch a Navigation Item multiple times. It will show multiple instances of PopOver. How can I handle it, so it will show only one instance?
I had the same problem and mostly found the solution here. Basically you change the action of the button each time it's pressed to either display or dismiss the popover. Here's the code I ended up with:
#interface FilterTableViewController : UITableViewController {
UIPopoverController *editPopover;
id saveEditSender;
id saveEditTarget;
SEL saveEditAction;
}
-(void)prepareForSegue:(UIStoryboardPopoverSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"EditFilterSegue"]){
// Save the edit button's info so we can restore it
saveEditAction = [sender action];
saveEditTarget = [sender target];
saveEditSender = sender;
// Change the edit button's target to us, and its action to dismiss the popover
[sender setAction:#selector(dismissPopover:)];
[sender setTarget:self];
// Save the popover controller and set ourselves as the its delegate so we can
// restore the button action when this popover is dismissed (this happens when the popover
// is dismissed by tapping outside the view, not by tapping the edit button again)
editPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
editPopover.delegate = (id <UIPopoverControllerDelegate>)self;
}
}
-(void)dismissPopover:(id)sender
{
// Restore the buttons actions before we dismiss the popover
[saveEditSender setAction:saveEditAction];
[saveEditSender setTarget:saveEditTarget];
[editPopover dismissPopoverAnimated:YES];
}
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
// A tap occurred outside of the popover.
// Restore the button actions before its dismissed.
[saveEditSender setAction:saveEditAction];
[saveEditSender setTarget:saveEditTarget];
return YES;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Before we navigate away from this view (the back button was pressed)
// remove the edit popover (if it exists).
[self dismissPopover:saveEditSender];
}

Resources