View locked out after UIActionSheet or UIAlertView (iPhone / iPad) - iphone

I'm having some trouble with either a UIAlertView or UIActionSheet stealing the focus and not letting go.
To elaborate, I have a setup whereby a user presses a button. This then displays a UIAlertView with a UITextField. When the user presses the 'Ok' button a UIActionSheet is displayed (called from the UIAlertView delegate method) confirming something with the user. However when they press one of the buttons the UIActionSheet goes away but the focus doesn't get returned to the main view.
I have been playing around and whatever I seem to do I always end up with my main UIView being covered with a layer like this (obviously you can seem my view through the layer). I have tried removing all subviews of the view but it didn't have any success.
Please can someone help me out?
Here is the source code:
// This method displays the UIAlertView which contains a UITextView linked up to a
// UIPickerView.
- (IBAction)buttonPressed:(id)sender
{
UIAlertView *deleteAlert = [[UIAlertView alloc] initWithTitle:#"Delete Something"
message:#"Select something to delete:"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
deleteAlert.alertViewStyle = UIAlertViewStylePlainTextInput;
deleteAlert.tag = kDeleteAlert;
deleteTextField = [deleteAlert textFieldAtIndex:0];
[pickerView reloadAllComponents];
deleteTextField.inputView = pickerView;
[deleteAlert show];
}
// The UIAlertView delegate method is then used to display a UIActionSheet to confirm
// whether the user wants to proceed.
- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
UIActionSheet *confirmDelete = [[UIActionSheet alloc] initWithTitle:#"Delete blah?"
delegate:self
cancelButtonTitle:#"No"
destructiveButtonTitle:#"Yes"
otherButtonTitles:nil];
confirmDelete.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[confirmDelete showInView:self.parentViewController.tabBarController.view];
}
// Then the focus should be returned to the original view (i.e. where the first button
// was pressed to launch the UIAlertView. However the focus is still locked and the
// view appears slightly dimmed around the edges.
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == actionSheet.destructiveButtonIndex)
{
// Do some stuff ...
}
}

I think your issue is a result of the deleteAlert alert view not being dismissed when the actionSheet is called.
I sounds to me like the alert view still has focus but is in an unknown state, because it hasn't been dismissed, but you have done something with it's button press.
Presumably, you want to dismiss the alert view when the action sheet is presented? Then when the action sheet is dismissed, you get back to your main view? So, the order you want:
1) Present alert view
2) If a button on the alert view is pressed, it notifies it's delegate using - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
3) Dismiss the alertView - (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated and present the action sheet.
3) When the action sheet is used, it calls it's delegate method - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex and within that method, dismiss it, or whatever else you need to do.
You would put all of these delegate methods in your original calling viewcontroller, conforming it to <UIAlertViewDelegate, UIActionSheetDelegate>.
You will need to make the original viewcontroller the delegate of the alert view AND the action sheet when you create them. I hope this makes sense.
More information http://developer.apple.com/library/ios/#documentation/uikit/reference/UIAlertView_Class/UIAlertView/UIAlertView.html

I would say it's probably b/c you are not resigning the first responder on the UITextField that is inside the UIAlertView. Make sure that before you show your UIActionSheet you do
[myTextField resignFirstResponder];

Related

Showing UIActionSheet over UIAlertView

For a specific server notification I am supposed to show an UIActionSheet. But problem here is when that event comes, at the same time if any UIAlertView already showing on any view controller, it make the UIActionSheet disabled( After pressed ok for alert view I am not able to select anything on view controller , view got disabled because of UIActionSheet). Anyone faced this kind of problem, Any idea how to solve it?
I have tried by dismissing alert view before showing action sheet, however which alert view do I need to dismiss as I have many alert view in many controller. All are local to that controllers. How to solve this problem.
Note:
Same problem won't come for iPod, as it wont allow to click ok before responding to UIActionSheet.
Take a Global Alert view named it as activeAlertView. Now when you show a alert view please check that alert view and then show and assign. Like
declare a property in .h and synthesize it
#property (nonatomic, retain) UIAlertView *activeAlertView;
then use the below code when try to show an alert.
if(self.activeAlertView){
[self.activeAlertView dismissWithClickedButtonIndex:0 animated:YES];
}
UIAlertView *localAlert = [[UIAlertView alloc] initWithTitle:#"Title" message:#"Your message" delegate:nil cancelButtonTitle:#"cancel" otherButtonTitles:nil, nil ];
[localAlert show];
self.activeAlertView = localAlert;
[localAlert release];
this way your activeAlertview will keep the current aler view's reference and before show the actionSheet dismiss the alert view.
For Identified which alert-view you must set Tag or alert-view.
Ex:-
alertviewName.tag=1;
Then you can check is there alert-view Open in Particular view-controller sub-views use bellow code like:-
- (BOOL) doesAlertViewExist {
for (UIView* view in yuorviewcontroller.view.subviews) {
BOOL alert = [view isKindOfClass:[UIAlertView class]];
if (alert)
{
return YES;
}
}
return NO;
}
After this method called you get BOOL value YES or NO If Yes then dismiss it using UIAlertview's Delegate:-
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex;
and put your Actionsheet appear code into didDismissWithButtonIndex method.
When the message comes, first check if there is an alert view.
Show the action sheet after the alert view is dismissed. In didDismiss... you can check a BOOL flag if you now have to show the action sheet or not.
In this case, you should use
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
method rather than,
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
so your code wil be:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
UIActionSheet *actionSheet = ...
[actionSheet showFromTabBar:self.tabBarController.tabBar];
}
}
Thanks
try this:
for (UIWindow* w in [UIApplication sharedApplication].windows)
{
for (NSObject* obj in w.subviews)
{
if ([obj isKindOfClass:[UIAlertView class]])
{
[(UIAlertView*)obj dismissWithClickedButtonIndex:[(UIAlertView*)obj
cancelButtonIndex] animated:YES];
}
}
}

Action Sheet Within ActionSheet

am new to Objective C and iPhone Development.
Kindly tell me how can i add an action sheet within action sheet.
Like when i tap a button an action sheet is opened and then I clicked the first ButtonIndex of action another action sheet appears.
Kindly mention the complete code.
Thanks
Use the UIActionSheet delegate method:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) { // Add an action sheet for one of these buttons -> maybe here if you want...
NSLog(#"You clicked the first button...");
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:#"Another action sheet"
delegate:self cancelButtonTitle:#"Cancel Button" destructiveButtonTitle:#"Destructive"
otherButtonTitles:#"Other Button 1", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[popupQuery showInView:self.view];
[popupQuery release];
}
else {
NSLog(#"Dismissing action sheet");
}
}
All you want to do is dismiss the first UIActionSheet and show another UIActionSheet in it's place. In other words, you don't want to show a UIActionSheet within another UIActionSheet -- you want to show a UIActionSheet after a different UIActionSheet has been dismissed.
To find out when an action sheet is being dismissed, you should implement the UIActionSheetDelegate protocol. For example:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
// first action sheet is dismissed
// show a new action sheet here
}

How the UIActionSheet works?

When popping a view I want to save some data, by asking confirmation. I'm asking confirmation using UIActionSheet. But irrespective of my response in action sheet, the view is changing in background, it creates some problem for me to use the response. I'm using navigation controller to switch views. How can I solve this
TIA
Better option is to use uialertview for asking confirmation.To do this follow this step:
Insure your header file contains the following:
#interface YourViewController : UIViewController <UIAlertViewDelegate>
Now when asked confirmation add this code:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Message" message:#"Are You Sure" delegate:self cancelButtonTitle:#"YES" otherButtonTitles:#"NO", nil];
[alert show];
[alert release];
Now after pressing one button below delegate will be called so add in .m file of app
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the YES/NO buttons
if (buttonIndex == 0)
{
NSLog(#"NO button pressed");
}
else
{
//Save data here
NSLog(#"YES button pressed");
}
}
#PooLas If I understood you correctly, You use uiactionsheet for user confirmation, while in background (actually under actionsheet) you change view controllers. Well, you can't do that, because delegate must be attached to controller which shows it up (if i am wrong, correct me). So when you click button, you can only first dismiss actionsheet and then change view controller, but not opposite – PooLaS

iOS - How can I show a UIImagePicker over a UITableView?

I have a table cell which, when selected, should allow the user to select an image from photo library or take a new image.
The screen structure is:
UITabBar -> UINavigationController -> ParentController -> MyController
The code to achieve this in MyController is
- (void)showPhotoMenu
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:nil
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Take Photo", #"Choose From Library", nil];
[actionSheet showInView:self.view];
} else {
[self choosePhotoFromLibrary];
}
}
When tapping the cell, I get the option to choose from Library or take a photo but nothing seems to happen after that. The log output shows
Presenting action sheet clipped by its superview. Some controls might not respond to touches. On iPhone try -[UIActionSheet showFromTabBar:] or -[UIActionSheet showFromToolbar:] instead of -[UIActionSheet showInView:].
But I'm not sure that's why the ImagePicker screens (photo library or camera) won't display.
From what I gather, that's warning that the cancel button won't be accessible because the tab bar covers it?
Can anyone advise where I might be going wrong here?
There is not enough of the code to say for sure but the
Action Sheets uses your code as a delegate and returns control to you in a fixed delegate method
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == actionSheet.firstOtherButtonIndex + 0) {
//code to take photo
} else if (buttonIndex == actionSheet.firstOtherButtonIndex + 1) {
//code to take access media
}
}
The other warning message - Do you or do you not see all options in your action sheet?
[actionSheet showInView:self.view];
There are a few more options depending on if you have a navigation bar or a Tab bar, I have an iPhone program with more Action Sheet choices than you and I never get the error.

Action sheet doesn't show Cancel button on iPad

On the iphone, this code shows the cancel button:
- (IBAction)buttonPressed
{
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Are you sure?"
delegate:self
cancelButtonTitle:#"No way!"
destructiveButtonTitle:#"Yes, I'm sure!"
otherButtonTitles:nil];
[actionSheet showInView:self.view];
[actionSheet release];
}
But on the iPad, only the destructive button shows.
What's the problem?
This is part of the UI design and guidlines. Under 'Action Sheet' they say:
Do not include a Cancel button,
because people can tap outside the
popover to dismiss the action sheet
without selecting one of the other
alternatives.
It looks like the SDK hide the button for you on purpose. I'm not sure there is a solution, but maybe you could add your own button and set the cancelButtonIndex to match. Or you could switch to UIAlertView.
In iOS 5, this worked for me.
- (void)manualAddModel
{
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle: #"Select Equipment Type"
delegate: self
cancelButtonTitle: #"Cancel"
destructiveButtonTitle: nil
otherButtonTitles: #"Add Boiler", #"Add Furnace", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleDefault;
[popupQuery addButtonWithTitle:#"Cancel"];
[popupQuery showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSLog(#"Add Boiler");
}
else if (buttonIndex == 1)
{
NSLog(#"Add Furnace");
}
else if (buttonIndex == 2)
{
NSLog(#"Cancel Button Clicked");
}
}
Normally, tapping outside the actionsheet will serve the same purpose in iPad.
It looks like in iOS 4.2.1 you can manually add your own Cancel button like a normal button:
[actionSheet addButtonWithTitle:#"Cancel"];
And then set:
actionSheet.cancelButtonIndex = <your index>;
You won't get the red cancel button, but you will get either a blue or black one depending on your UIActionSheetStyle setting. In any event, it is pretty clearly distinguishable from the normal buttons and does correctly cancel.
Note that in my case I am showing an action sheet from within a popover controller, your results may vary in other scenarios.
I was able to solve this by setting the actionSheetStyle:
actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;
UIActionSheetStyleBlackTranslucent also works. I am displaying the action sheet from a modal view controller which I guess is not technically a "popovercontroller" like the guidelines say but not seeing a Cancel button on the action sheet doesn't look right when it appears on top of the modal view. All the user sees is one scary red button with no visible alternative.
Maybe I could change the modal view controller to a popovercontroller but then it wouldn't be modal which it needs to be.
--Update--
Well it was fun while it lasted but this no longer works in iOS 4.2.
I switched to using a UIAlertView instead of a UIActionSheet.
I no longer get a cool red button but it gets the job done.
I had the same issue when I tried to show ActionSheet in the View that was under another modal view, e.g. the view was invisible. Though the View wasn't nil looks like deep in framework it means so when it's not shown.
I solved the problem by setting a different UIModalPresentationStyle modalPresentationStyle property so the view became visible.
view.modalPresentationStyle = UIModalPresentationFormSheet;
According to iOS standard Cancel button is not displayed in UIActionSheet when displayed in iPad since UIActionSheet can be cancelled (Hide) by simply tapping any where outside ActionSheet region. In case of iPhone UIActionSheet will contain Cancel button.
Refer this link for further information UIActionSheet Cancel button in iPad