I have a UIAlertView that has the buttons "OK" and "Cancel". I'd like to present a modal view controller when the OK button is pressed. Here's what I have done so far:
Created the UIAlertView box. Implemented UIAlertViewDelegate protocol. Implemented (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex method.
In the above method, when buttonIndex == 0, I'm trying to do something to the effect of:
if (buttonIndex == 0)
{
ModalViewController *mdvc = [[[ModalViewController alloc] initWithNibName:nil bundle:nil] autorelease];
[self presentModalViewController:mdvc animated:YES];
}
As it turns out, the modal view does not present itself. I tried many other approaches but they are just making it complex and making me create a lot of unnecessary variables. There MUST be an easier way.
Some Extra Information:
If it matters in anyway, this is an OpenGL ES application.
If I invoke [self presentModalController:] as a result of a UIButton press, it does work as expected - I see the modal view controller.
I was having this problem as well. It seems clear the alert must be gone before the modal can present, so you're looking for a way to know the alert is gone. Skimming the docs, there is a simple way.
Instead of presenting your modal when this is called:
- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
Use:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
This worked like a charm for me. From the documentation:
This method is invoked after the animation ends and the view is
hidden.
Alright... so I fixed this myself. As I said, this was in an OpenGL ES application, so I set some global bools and called the [self presentModalViewController] in the drawFrame method. This is definitely not the best method, I know, but in the time-crunch I am in, there seems to be no better solution!
The issue is certainly delay-related but performSelector:withObject:afterDelay doesn't seem to be sufficient!
First, move that code to a new method named presentModal:
- (void)presentModal:(UIViewController *)mvc {
[self presentModalViewController:mvc animated:YES];
}
Then, in the method where you handle the response from the UIAlertView, call this new method, like this
ModalViewController *mdvc = [[[ModalViewController alloc]
initWithNibName:nil
bundle:nil] autorelease];
[self performSelector:#selector(presentModal:)
withObject:mdvc
afterDelay:0.0];
That will postpone the execution of the presentModal: method until after the method handling the UIAlertView has returned, and after the UIAlertView has been removed from the screen.
The Cancel button has index of 0, the OK button will have index of 1. Are you sure you are doing the action on the correct button index? (i.e. if you press 'Cancel' does it show the modal?).
Related
I have an educational app working fine with tab bars. One of the tabs is a test for the user. If a user taking the test selects another tab, I would like an action sheet to display to confirm they really want to exit the test since their test results will be lost.
I can't get the action sheet to display. I am getting syntax errors with the first three examples below. The 4th example will compile OK but the app aborts. I can't figure out what should go after the self. Or possibly one of the other examples would work if I had the syntax correct.
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController {
NSLog(#"Tab Bar Controller reached");
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"This will end the test.
Are you sure you want to leave?"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:#"Yes,
cancel the test."
otherButtonTitles:nil];
[actionSheet showInView:self.view];
[actionSheet showInView:elements1AppDelegate.window];
[actionSheet showFromTabBar:self.tabBarController.tabBar];
[actionSheet showFromTabBar:self];
Ultimately, once I get the action sheet to display, I will either proceed to the tab selected or stay in the test view depending on whether the user decides to exit or not. Any help/suggestions would be appreciated. Thanks.
The name of the method tabBarController:didSelectViewController: should indicate that it's too late to stop the selection. Its return type void indicates there is not much you can do about it. Instead focus on method names that have "will" or "should" in them, and return types like BOOLs such as tabBarController:shouldSelectViewController:. So here is some basic code that does what you want.
I don't know the actual classname of your test's view controller so I'll use QuizController as a classname. QuizController is a UIViewController subclass.
QuizController.m
#interface QuizController () <UITabBarControllerDelegate,UIActionSheetDelegate>{
BOOL _testInProgress;
}
#end
#implementation QuizController
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
// When a tabs view controller is presented viewDidAppear: will be called so here we will set this view controller as the tabBarController delegate so we get the callback.
self.tabBarController.delegate = self;
}
-(void)startQuiz{
_testInProgress = YES;
// Begin testing code
}
-(void)stopQuiz{
// Score test record results
_testInProgress = NO;
}
-(void)cancelQuiz{
// Throw out results
_testInProgress = NO;
}
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
if (!_testInProgress) return YES;
// If trying to select this controller then who cares?
if (viewController == self) return YES; // Or NO. Just don't show the sheet.
UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:#"You are in the middle of a test. Are you sure you want to switch tabs?"
delegate:self
cancelButtonTitle:#"Continue Test"
destructiveButtonTitle:#"Abort Test"
otherButtonTitles:nil];
// Lets cheat and use the tag to store the index of the desired view controller.
action.tag = [self.tabBarController.viewControllers indexOfObject:viewController];
[action showFromTabBar:self.tabBarController.tabBar];
return NO;
}
-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex{
if (buttonIndex == actionSheet.destructiveButtonIndex){
[self cancelQuiz];
// The above cheat pays off.
[self.tabBarController setSelectedIndex:actionSheet.tag];
}
}
EDIT (In response to comment quoted)
I'm a little confused about your example. Currently, my "take test"
class is a UIViewController. Are you suggesting I replace that with
your QuizController above?
No. I am suggesting that you take this code and integrate the design pattern into your UIViewController subclass that handles your test. Although this is a working example (providing you supply UI to toggle the _testInProgress ivar.)
Do I leave my current UITabBarController in place?
Yup.
That is currently my appdelegate and rootController.
Huh? Your UITabBarController is almost certainly your rootViewController. But unless you have done something very odd like AppDelegate : UITabBarController <UIApplicationDelegate>, by the way don't do that, then it is extremely unlikely that your "appdelegate" and your UITabBarController are the same. Much more likely your AppDelegate is your tabBarController's delegate.
If just setting the tabBarController.delegate property on appearance is bad (and it could very well be), i.e. some other object needs to be the tabBarController's delegate, then you'll have to forward a message to that view controller to see if a test is in progress. For this you could actually leave almost all of the code in the example unchanged. Of course you would have to remove the self.tabBarController.delegate = self; in viewDidAppear:. And put the following in your AppDelegate(presuming that's the tabBarController's delegate):
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
if ([tabBarController.selectedViewController respondsToSelector:#selector(tabBarController:shouldSelectViewController:)]){
return [(NSObject <UITabBarControllerDelegate>*)tabBarController.selectedViewController tabBarController:tabBarController shouldSelectViewController:viewController];
}
return YES;
}
This implementation essentially forwards the responsibility to answer the question to the view controller, provided it will answer the question.
I check in there if the "take test" tab was selected and call an
initialization method in my "take test" class.
In my opinion the "take test" view controller should simply become selected when the user taps the tab for it. And its view should contain a button with something to the effect of 'start test' on it. But that's just my opinion.
But whatever the case is the application's knowledge of whether the user is taking a test should reside in the view controller that administers the test.
[actionSheet showInView:[[[UIApplication sharedApplication] windows] objectAtIndex:0]];
Did you try this One Link
Hi I have three views and I would like to achieve something that doesn't work. I have a main view if user presses a certain button the code checks if he is logged or not:
if yes he is sent directly to view B if not first he goes to login view.
After successfull login I have this code to go to view b:
incidencias =[[MisIncidencias alloc]
initWithNibName:#"MisIncidencias"
bundle:nil];
[self.view addSubview:incidencias.view];
the thing is I would like to get rid of the login view because it shows there underneath plus if user clicks back it goes back to login but if I add:
[self.view removeFromSuperview];
either before or after [self.view addSubview:incidencias.view], I just get redirected to the main view;
I don't know if I explained myself clearly but for example in Android you can just call finish and then call next activity and the login activity disappears but here in iphone I don't know what to do.
I have found another solution is to add both views one after another but it doesn't really work well:
incidencias=[[MisIncidencias alloc]
initWithNibName:#"MisIncidencias"
bundle:nil
];
[self.view addSubview:incidencias.view];
login=[[LoginViewController alloc]
initWithNibName:#"LoginViewController"
bundle:nil];
[self.view addSubview:login.view];
it doesn't work well because incidencias starts and doesn't wait for login to finish.
thanks
EDIT: thanks to beOn I have modified my code adding the protocol:
LoginViewControllerDelegate
and this method inside viewController:
- (void)loginSucceededFromController:(LoginViewController*)viewController {
[viewController.view removeFromSuperview];
incidencias =[[MisIncidencias alloc]
initWithNibName:#"MisIncidencias"
bundle:nil];
[self.view addSubview:incidencias.view];
}
in LoginViewController I have
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex: (NSInteger)buttonIndex{
if(self.delegate)
[self.delegate loginSucceededFromController:self]
}
it gets an error:
Semantic Issue: Property 'delegate' not found on object of type 'LoginViewController *'
if login is successful the user sees an alert and once he clicks on ok is when the method above gets called.
what else should I add? I am beginning with iphone and I don't understand very well what is delegate (I come from java)
Ah, okay, this ain't so bad. Here's the first solution that comes to mind:
Step 1. Create a delegate protocol for your login view.
#protocol LoginViewControllerDelegate <NSObject>
#required
- (void)loginSucceededFromController:(LoginViewController*)viewController;
#end
Step 2. Implement the protocol in your main view controller
- (void)loginSucceededFromController:(LoginViewController*)viewController {
// TODO: we'll put something here in a second
}
Step 3. Call the delegate method from your login view on successful login
if (loginSuccess && self.delegate) {
[self.delegate loginSucceededFromController:self]
}
Step 4. Dismiss the login view and present the new view from the main view controller using the code you already have:
- (void)loginSucceededFromController:(LoginViewController*)viewController {
[viewController.view removeFromSuperview];
incidencias =[[MisIncidencias alloc]
initWithNibName:#"MisIncidencias"
bundle:nil];
[self.view addSubview:incidencias.view];
}
Hopefully that clears things up some. The reason you were having trouble is that you were either adding a subview to a view, then immediately removing the view, or removing the view, then adding a subview to it. In the code above, you call the view's controller's delegate, and the delegate, which happens to own the superview of the view, first removes the view, then adds a newView (for lack of a better term) to the superview. Since the superview was never removed, it's able to show your newView.
You have to take BOOL which one can access through out application like global
like extern BOOL login; now once you login set to YES. now check when
if(login == YES){
incidencias=[[MisIncidencias alloc]
initWithNibName:#"MisIncidencias"
bundle:nil
];
[self.view addSubview:incidencias.view];
}
else{
login=[[LoginViewController alloc]
initWithNibName:#"LoginViewController"
bundle:nil];
[self.view addSubview:login.view];
}
If you want something working right away, and you are using uinavigationcontroller... then u can possibly make use of
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated
just get a mutable copy of the self.navigationController.viewcontrollers array, pop out the last element, which will be the login screen and push in the new screen where you are planning to move screen b.. and pass the array to this function.. and you are now safe!
In my UIViewController I have a UINavigationController with a default back button. When the user clicks the back button, a warning message should appear: "Do you really want to go back?". I know, that it is not possible to trap the back button event. It's only possible the use viewWillDisappear and set a flag:
- (void)viewWillDisappear:(BOOL)animated {
if (backBtnPressed) {
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Question" message:#"Do you really want to go back?" delegate:self cancelButtonTitle:#"No" otherButtonTitles: #"Yes", nil] autorelease];
[alert show];
}
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
// don't go back!
// cancel the back button event
}
else if (buttonIndex == 1) {
// go back
}
}
But with this code I have no chance! I can't stop the back button event, isn't it?
Do I have to write my own back button and set it as leftBarButtonItem? Or is there anybody with a great idea? :-)
Thanks for your help!
My answer from another thread matches this question. So I repost it here:
I've implemented UIViewController-BackButtonHandler extension. It does not need to subclass anything, just put it into your project and override navigationShouldPopOnBackButton method in UIViewController class:
-(BOOL) navigationShouldPopOnBackButton {
if(needsShowConfirmation) {
// Show confirmation alert
// ...
return NO; // Ignore 'Back' button this time
}
return YES; // Process 'Back' button click and Pop view controller
}
Download sample app.
What you need to do is to use the delegate of the navigation bar, and not the navigation controller.
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item; // called to push. return NO not to.
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item; // called at end of animation of push or immediately if not animated
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item; // same as push methods
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;
viewWillDisappear is a delegate method for the event that the view is going to disappear - and there's nothing the developer can do about that! If you could, it would be a viewShouldDisappear delegate method.
So I guess the only way is as you suggest, to use a custom leftBarButtonItem.
I must say this is one of the common use cases that Apple doesn't seem to make easy, and I see a lot of effort trying to get this working. I thought maybe I should summarize my findings here.
As many have pointed out, the method below in UINavigationBarDelegate is key to implementing this feature.
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
Many have subclassed UINavigationController and implemented the method above to make it easy to use without direct access to the UINavigationBar.
Unfortunately, there still remain some issues.
The swipe back gesture does not invoke this method.
Although it seems necessary, crashes are reported calling popViewControllerAnimated: in this method.
The Back button remains grayed out, when pop is cancelled.
Swipe back gesture
We need to intercept the gesture by setting the delegate as is done in https://stackoverflow.com/a/23173035/2400328 .
If the UINavigationController is subclassed, that would be:
self.interactivePopGestureRecognizer.delegate = self
and implementing:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
Take care in when you modify the delegate property, as it gets modified after the initializer is called.
Not calling popViewControllerAnimated:
Although undocumented, calling popViewControllerAnimated: can be avoided as in https://stackoverflow.com/a/26084150/2400328.
It involves calling navigationBar:shouldPopItem: of UINavigationController (from the subclass).
The Back button
Although this may be a minor detail (especially, if you have designed your own Back button), there is a simple solution (written by me :) https://stackoverflow.com/a/29440633/2400328
You only need to set a property YES and NO.
auto item = navigationBar.topItem;
item.hidesBackButton = YES;
item.hidesBackButton = NO;
You can use a custom button with a graphics, which looks exactly like "Back" button and create a custom leftBarButtonItem view as UIButton with this graphics. Add target self to your button with custom back: selector and pop your alert there. If the user presses "yes" to quit dismiss this view controller, if not - do nothing. The trick here is the button which looks exactly as navigation bar's back button.
Its better if u make your own back button and make it the left button of the Navigation controller. That can definitely help u to perform any action
If you're looking for a way to do this in Swift on iOS 10, you can create a custom UINavigationController and then a UINavigationBarDelegate extension:
class MyNavigationController : UINavigationController {
}
extension MyNavigationController : UINavigationBarDelegate {
public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
return false
}
}
The Method
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
is doing what you want. Unfortunately we are not supposed to delegate UINavigationBar to our own objects :(
The Apple Documentation states :
... In addition, a navigation controller object automatically assigns itself as the delegate of its UINavigationBar object and prevents other objects from changing that relationship. ...
One/The? way to do what you want is to put in your own back-button.
In that Method you do your tests and call
[self.navigationController popViewControllerAnimated:true];
if the user is allowed to go back.
I don't get a call to my eventViewController:didCompleteWithAction: when the EKEventViewController finishes edting an event.
Here's how I set it up:
- (void)showCalendar:(id)sender {
EKEventViewController *eventViewController = [[EKEventViewController alloc] init];
eventViewController.delegate = self;
eventViewController.event = self.event;
// Allow event editing.
eventViewController.allowsEditing = YES;
[self.navigationController pushViewController:eventViewController animated:YES];
[eventViewController release];
}
I do have the protocol on my class and the method was implements by copy and pasting the definition from the docs. It just doesn't get called.
If I use the EKEventEditViewController and its corresponding delegate, then that does get called when the event is saved.
I was able to reproduce the problem in the SimpleEKDemo code same as well. Does anyone know what might be wrong?
I could just drop the view functionality and go straight to the EKEventEditViewController, but I'd rather not.
Might be a bit late to be helpful, but I had this problem as well.
To get around it I subclassed EKEventViewController, then in the subclass' viewDidLoad I replaced the standard edit button with one of my own:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *editItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self.delegate action:#selector(editCalEvent)];
self.navigationItem.rightBarButtonItem = editItem;
}
That way when you want to edit an event, you can set up your own EKEventEditViewController and specify its delegate in order to respond to changes:
- (void)editCalEvent {
EKEventEditViewController *editController = [[EKEventEditViewController alloc] init];
editController.event = editingEvent;
editController.eventStore = self.eventStore;
editController.editViewDelegate = self;
[self presentModalViewController:editController animated:YES];
[editController release];
}
Hope that helps.
I had the similar problem when I use "pushViewController", the result is that it will go to
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{}
But after I changed to presentModalViewController, it will go to eventViewController:didCompleteWithAction: when Done/Cancel/Delete are pressed.
in this .m file you need to import the EventKit/EventKit.h and EventKitUI/EventKitUI.h
and in the .h file you need to implement the 'EKEventViewDelegate' delegates.
hope it helps you
This does seem to be a fairly obvious omission in the library. My workaround: I'm presenting the EKEventViewController in a UINavigationController. I detect completion in the viewWillAppear method of the controller than pushed the EKEventViewController onto the view stack. Use a boolean variable in this view controller to track and differentiate between initial appearance and re-appearance due to the EKEventViewController being popped. There is a risk that your code will get called at other times, but if you are just refreshing tableviews, etc, then this should be sufficient.
My modal view controllers are being shown behind my UIActionSheet, and my UIActionSheet is not getting dismissed. I am using:
[self presentModalViewController:composeTweetView animated:YES];
To present my modal view controller.
My action sheet is being shown from the tabBar:
[actionSheet showFromTabBar:self.parentViewController.tabBarController.tabBar];
This code worked on iOS 4.0.
if (buttonIndex == 0) {
if (self.isLoggedIn) {
[FlurryAPI logEvent:#"ST_REPLY_CLICKED"];
composeTweetView.isDirectMessage = FALSE;
[self presentModalViewController:composeTweetView animated:YES];
[composeTweetView release];
}
else {
LoginViewController* loginView = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
loginView.delegate = self;
loginView.isPostingComment = TRUE;
self.isReply = TRUE;
[self presentModalViewController:loginView animated:YES];
[loginView release];
[composeTweetView release];
}
}
Summary:
I have a UIViewController that contains a UITabBar. I am presenting a UIActionSheet which has a few buttons that present a modal view controller. When the modal view controller is presented, the UIActionSheet should dismiss itself and the modal view should be on the top of the stack. The problem is, the UIActionSheet does not dismiss, and the modal view is loaded behind it. This problem did not occur up until iOS 4.2.1
Steps to Reproduce:
Create a TabBar project, setting
your Base SDK to iOS 4.2.1
Create a button or trigger to show a UIActionSheet
Allow one of the buttons in the UIActionSheet to present a modal view controller using the syntax: [actionSheet showFromTabBar:self.parentViewController.tabBarController.tabBar];
Expected Results:
1. The UIActionSheet should dismiss itself, and the modal view should appear in front
Actual Results:
1. The UIActionSheet does not get dismissed and the modal view appears behind it.
Regression:
This problem was not apparent prior to iOS 4.2.1
Notes:
I have tried other ways of displaying the UIActionSheet all of which don't work as intended:
//[actionSheet showInView:self.parentViewController.tabBarController.tabBar];
//[actionSheet showInView:[self.view window]];
//[actionSheet showInView:self.parentViewController.tabBarController.view];
//[actionSheet showInView:[UIApplication sharedApplication].keyWindow];
In putting together a sample in order to reproduce your problem I took a look at the UIActionSheet delegate methods. I believe you can use:
actionSheet:didDismissWithButtonIndex:
instead of
actionSheet:clickedButtonAtIndex:
I haven't tested it, but I believe you still get the same button number and it doesn't fire until the actionsheet has disappeared from the view.
I don't understand your problem sorry but everything works great for me. I have tried the following code in Simulator and on 4.2.1 iPod Touch 4G (both worked)
- (IBAction)doit {
UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:#"title" delegate:self cancelButtonTitle:#"not OK" destructiveButtonTitle:#"Absolutely" otherButtonTitles:nil];
[actionSheet showFromTabBar:self.tabBarController.tabBar];
[actionSheet release];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
UIView *v = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
v.backgroundColor = [UIColor redColor];
[self.view addSubview:v];
[v release];
}
}
created the TabBar sample project
added button to firstView-nib and connected with the appropriate IBAction (have to name the FileOwner to FirstViewController)
set the delegate method in FirstViewController.h (<UIActionSheetDelegate>)
added the code above
//EDIT: ok I saw that you want to present it modally but even this works for me on 4.2.1
TMPController *tmp = [[TMPController alloc]initWithNibName:#"TMP" bundle:nil];
[self presentModalViewController:tmp animated:YES];
[tmp release];
maybe it works because I use self.tabBarController.tabBar, try that
Not sure if you have already resolved this. But I didn't see a clear answer above. I was having exactly the same problem as you. So in the end, it was an issue on my side, but what help me debug this was to add the actual action code in the method
actionSheet:didDismissWithButtonIndex:
as suggested by Matthew.
This proved that the view was actually dismissed. That's when I realized that I put the UIActionSheet alloc in my viewWillAppear method. So each time the view appears it re-creates the action sheet.
This seems weird as the SDK Documentation states:
actionSheet:clickedButtonAtIndex:
…
The receiver is automatically dismissed after this method is invoked.
I can think of 3 possibilities why it may not disappear:
The main runloop (main thread!) which handles the animations and display stuff is not called. Do you work something heavy in your main thread like synchronous networking calls? (note the word "after" in the SDK text)
Somehow you schedule to show the action sheet multiple times
You display the same view controller instance modally that is already somewhere below the current view on the view stack.
I just wrote a quick sample app to test this out and it worked just as I expected (i.e., I couldn't repro your issue). It was a little different in that I didn't do a TabBar application but I'm still hopeful this helps. What I did with the UIActionSheet was to show it like this: [actionSheet showInView:self.view]. Maybe that will work?
Sorry for the rushed answer, I was on my way out when this caught my eye. :)
I have also faced problems like this with iOS 4.2.
I think you should try with the following steps:
Create a separate method for the code you want to be executed on clicking the actionsheet button. suppose the method is -(void)presentModalView{}
2.Now in the - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex method,Call the presentModalView{} method for the clicked button index like this:
if(buttonIndex==0)
{
[self performSelector:#selector(presentModalView) withObject:nil afterDelay:0.3];
}
3.You can also try by different delay time.
Hope it helps..
I had the same issue calling MailComposeView from AlertBox/ActionSheet caused the MailCompseView to come behind invisible screen.
I solved it by calling dismissWithClickedButtonIndex:animated: in the actionSheet button handler.
The problem has been resolved in iOS5.