In my app when the user clicks a button it calls a prepareForSegue. The app need to check a state and then prompt the user if they want to over write or delete. Problem is that it loads the next view controller before the UIActionSheet is displayed. How can I force the UIActionSheet to appear before the prepareForSegue is called? This is my logic for prepareForSegue;
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"mySegue"]) {
//Check Logic removed for simplicity
if ([myCheck count] > 0){
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Save?"
delegate:self
cancelButtonTitle:#"Delete"
destructiveButtonTitle:#"Save"
otherButtonTitles:nil];
[actionSheet showFromToolbar:self.navigationController.toolbar];
}
}
}
Here is the Action sheet;
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == [actionSheet cancelButtonIndex])
{
//Delete logic removed
}else {
//Save logic removed
}
}
You won't be able to do it in a segue. You'll have to load the view controller manually in your action sheet handler when you get the button index that’s supposed to trigger it. That means whatever is triggering the segue now will have to be disconnected and pointed at an IBAction that will create and show your action sheet. prepareForSegue is intended to allow you to set parameters on your destination view controller prior to displaying it. The segue has already been set in motion by the time you get to prepareForSegue. At that point, there is no going back/canceling/delaying the performing of the segue.
Best Regards.
I have found it possible To peform a Segue from a action Sheet
As long as The segue Is from the View controller and and an Identifier here is a example.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == [actionSheet cancelButtonIndex]) return;
if (buttonIndex == 0) {
[self performSegueWithIdentifier:#"visitWeb" sender:self];
}
if (buttonIndex == 1) {
if ([MFMailComposeViewController canSendMail])
{
Might not be the correct way as I'm a bit of a newb but for my modal view controller on StoryBoard it seems to do the trick
Creating an action sheet is an asynchronous event and does not block the segue. You'll need to trigger the segue from your action sheet.
Related
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];
}
}
}
I got a push segue connected in storyboards and then I'm using the prepareForSegue method like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"start"] && self.name.textField.text == nil)
{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Test"
message:#"Test
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
}
}
What I want to do is that if the "if" is true, there pops an alert box and preforms the segue, but I just want to show the alert box, and I don't want to preform the segue. How can I solve this?
prepareForSegue:sender: is called when the segue is about to be performed. You cannot cancel it at that point.
The method you should be overriding if you want to be able to cancel a segue is shouldPerformSegueWithIdentifier:sender:.
I think you need to reevaluate your logic here and remove the conditional from prepareForSegue
Using UIAlertDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"OK"]) {
[self performSegueWithIdentifier:#"My Segue" sender:self];
return;
} // else do not perform segue
}
I dont think you can stop from at this point.
But you can use
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender from iOS 6.
Try giving your segue a different name and only call that segue (e.g. "[self performSegueWithIdentifier: #"MyRealStartSegue" sender: sender]") if the alert is not displaying.
Of course this means you need to check these conditions outside of the "prepareForSegue" method. Perhaps an IBAction when some button is pressed?
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 to switch views using UIActionSheet when cancel button is pressed ?
xcode 4.3.2
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:#"Done"]) {
thiredViewController *controller1 = [[thiredViewController alloc] initWithNibName:#"thiredViewController" bundle:nil];
[self presentModalViewController:controller1 animated:NO];
}
}
this code do nothing, the view didn't change, my friend told me that i can't use this method to change views in the new Xcode , so what should i use ?
You should never compare the title of a button to decide which action to take. What if you decide to change it elsewhere but forget to change your delegate method as well? This will also get messy if you localize your app in multiple languages.
UIActionSheet has a convenient cancelButtonIndex method that you can use for this:
if (buttonIndex == actionSheet.cancelButtonIndex) {
//do your thing...
}
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];