Objective C: AlertView does not work - objective-c

I am implementing an alert view after the user clicks on the 'destructButton' in an action sheet. Code snippet as below:
-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex != actionSheet.cancelButtonIndex)
{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Something happened!"
message:nil
delegate:nil
cancelButtonTitle:#"Phew!"
otherButtonTitles:nil];
}
[alert show];
[alert release];
}
I have already included the UIActionSheetDelegate protocol in my .h file
#interface Control_FunViewController : UIViewController <UIActionSheetDelegate> {
UITextField *nameField;
UITextField *numberField;
UILabel *sliderLabel;
UISwitch *leftSwitch;
UISwitch *rightSwitch;
UIButton *doSomethingButton;
}
But when I click on the destructButton in the actionsheet, nothing happens. Am I missing something here?
Thanks
Zhen

Your delegate needs to implement actionSheet:clickedButtonAtIndex:.
Action sheet will be dismissed after actionSheet:clickedButtonAtIndex: and after that the delegate will receive actionSheet:didDismissWithButtonIndex: .
From Apple Action Sheet Delegate Protocol reference
... the delegate must implement the
actionSheet:clickedButtonAtIndex:
message to respond when those buttons
are clicked; otherwise, your custom
buttons do nothing. The action sheet
is automatically dismissed after the
actionSheet:clickedButtonAtIndex:
delegate method is invoked.
You can have a look at example projects that use UIActionSheet like GenericKeychain :
// Action sheet delegate method.
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex
{
// the user clicked one of the OK/Cancel buttons
if (buttonIndex == 0)
{
[passwordItem resetKeychainItem];
[accountNumberItem resetKeychainItem];
[self.tableView reloadData];
}
}

You have added UIActionSheetDelegate on .h file. Not this only enough. You also have to set delegate for the UIActionSheet object. Refer this below coding:
-(void)showActionSheet
{
UIActionSheet *action =[[UIActionSheet alloc]initWithTitle:#"dsfs" delegate:self cancelButtonTitle:#"First Btn" destructiveButtonTitle:#"Dest Btn" otherButtonTitles:nil];
[action showInView:self.view];
}
In that code, I have set the delegate of UIActionSheet to self, this works if you have added this method on your ViewController (Control_FunViewController).

Related

Why is the UIAlertView not blocking until user responds by tapping a button?

In my iOS 7 app, I need to verify the user wants to deleta a selected record from Cord Data. I have the UIAlertViewDelegate defined in the .h file. This is the code to display the alert:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:#"Are you sure you want to delete this record?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Delete", nil];
[alert show];
if(alertButtonTapped == 0)
return;
// remainder of code to delete record follows (was omitted)
This is the code to check which button was tapped:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
alertButtonTapped = [NSNumber numberWithInteger:buttonIndex];
return;
}
The problem is the alert is displayed and then immediately falls through the remainder of the code in that method. I have never seen this before; usually it blocks until the user has responded by tapping one of the buttons (at least I thought it did). What do I need to do to make this alert block until the user responds? (I was looking at UIAlertView blocks, but not sure that would do the job since it appears to use a different thread)
This is how UIAlertView works -- it doesn't block, thus why it has the UIAlertViewDelegate methods for actually implementing a response.
If the "remainder of code" is what should happen after they tap a button (e.g. the "Delete" button), then move all of that code into the delegate method, like:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex != alertView.cancelButtonIndex) {
// code to delete record
}
}
EDIT - adding example to answer a comment
So if you have multiple UIAlertViews in the same class, you could differentiate between them using the tag attribute of UIView (UIAlertView is-a UIView). So it could be something like this:
const NSInteger kDeleteAlertTag = 100; // declared at the top of your .m file, perhaps.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:#"Are you sure you want to delete this record?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Delete", nil];
alert.tag = kDeleteAlertTag;
[alert show];
Then your delegate response might look like this:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView.tag == kDeleteAlertTag) {
if (buttonIndex != alertView.cancelButtonIndex) {
// code to delete record
}
}
else if (alertView.tag = kDoSomethingElseAlertTag) {
DoSomethingElse();
}
}

how to connect UIAlertView with what happens when the user makes a choice?

I have code setting up a UIAlertView:
-(IBAction)showMessage
{
//NSInteger *buttonIndex = NULL;
UIAlertView *message = [[UIAlertView alloc] initWithTitle:nil
message:nil
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Email",#"SMS",#"Facebook",#"Twitter", nil];
[message show];
}
and code explaining what to do once the user makes a choice:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1){
[self openMail];
}
else if (buttonIndex == 2)
//etc.
}
But what I can't figure out is how to connect the two. The obvious answer is to add a line to the first piece of code calling alertView: clickedButtonAtIndex on UIAlertView *message, but how do you assign buttonIndex? How do you tell alertView whether the user has chosen Facebook, Email, etc?
Add to the header file if you haven't already:
#interface YourClass : UIViewController <UIAlertViewDelegate>
{
}
...etc
and in your AlertView code change delegate:nil to delegate:self
For more information have a look at the Apple Docs:
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIAlertViewDelegate_Protocol/UIAlertViewDelegate/UIAlertViewDelegate.html
From the docs:
The button indices start at 0. If this is the cancel button index, the alert view is canceling. If -1, the cancel button index is not set.
(1) You want to set delegate:self when you initialize the message. Also, in your interface declaration, do something like:
#interface myClass: UIViewController <UIAlertViewDelegate>
This way, your handler function automatically gets called when the user makes a selection.
(2) Buttons are indexed in the order you listed them.
(3) Since you have a lot of options for the user to choose from, it is better to use UIActionSheet instead of UIAlertView. Alerts are generally used for simple Yes/No-type selections.
Hope this helps!

Is there a way to navigate to other views using a UIActionSheet?

Is there is a way to use an Action sheet to navigate to another view?
I have a button - "Go" and an Action sheet that asks "Do you want to proceed?" and in it "Yes" and "Cancel"
Can I can navigate to another view when pressing yes?
Yes, it is possible. To do this, the viewController that represents the UIActionSheet needs to adopt UIActionSheetDelegate. Upon dismissing the action sheet with either Yes or Cancel, - actionSheet:didDismissWithButtonIndex: method gets called, and from there you can navigate to another view or just ignore it.
References:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIActionSheet_Class/Reference/Reference.html#//apple_ref/occ/cl/UIActionSheet
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIModalViewDelegate_Protocol/UIActionSheetDelegate/UIActionSheetDelegate.html
Edit:
#interface MyViewController : UIViewController <UIActionSheetDelegate>
-(IBAction)showActionSheet:(id)sender;
#end
#implementation MyViewController
-(IBAction)showActionSheet:(id)sender {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Do you want to procced?" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"YES" otherButtonTitles:nil];
[actionSheet showInView:self.view];
}
-(void) actionSheet: (UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0: {
// for illustration
// let's assume (1) you have a navigation controller
// (2) you are using storyboard
// (3) in the storyboard, you have a viewController with identifier MyChildViewControllerIdentifier
MyChildViewController *mcvc = [self.storyboard instantiateViewControllerWithIdentifier:#"MyChildViewControllerIdentifier"];
[self.navigationController pushViewController:mcvc animated:YES];
break;
}
default:
break;
}
}
P.S. I didn't run it, if there is any error, let me know to fix it.
Dismiss the actionsheet and then [self presentmodalviewcontroller:myview animated:yes]

Open AlertView before calling method

I'd like to call a method
[self someMethod:bar]
But how can I open an AlertView before? someMethoud should wait for AlterView OK-Button. Do i need to write a complex task manager? Or is there a smart solution?
display the alert, and when the user clicks the button, then call your method.
remember to add the delegate to your class
#interface YourViewController : UIViewController <UIAlertViewDelegate>
code in your controller
// display the alert
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"Message"
delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
// UIAlertViewDelegate method - get the click here and take action
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
// ok button pushed
[self someMethod:bar];
}
}
You would need to implement the delegate method didDismissWithButtonIndex here http://developer.apple.com/library/ios/ipad/#documentation/UIKit/Reference/UIAlertViewDelegate_Protocol/UIAlertViewDelegate/UIAlertViewDelegate.html
The, depending on the button that was tapped, you would call your method.

NavigationController is not popping the Pushed View on Back button

Having a simple Navigation Controller in place (starting the Navigation Based Application project) I created a new View with a XIB file.
on my HomeViewController (Home screen with all options as UIButton's I have:
#implementation HomeViewController
-(IBAction) optionChoosed:(UIButton *)button
{
NSString *msg = [NSString stringWithFormat:#"Button: %d", button.tag];
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"Hi" message:msg delegate:nil cancelButtonTitle:#"Go away" otherButtonTitles:nil];
switch (button.tag) {
case 13:
// Simple Search
[self loadSimpleSearch]; break;
default:
[alert show];
break;
}
[alert release];
}
-(void)loadSimpleSearch
{
SimpleSearchViewController *controller =
[[SimpleSearchViewController alloc] initWithNibName:#"SimpleSearchViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
witch works great!
it Pushes the View into the front of the stack!
Now, because in my 2nd view SimpleSearchViewController I have self.title = #"myTitle"; I get the Title in the NavigationBar as well the back button (as I have the same setting on the HomeViewController)
I thought that the NavigationViewController would handle the pop of the current view, but it does not.
What do I have to do, to pop the SimpleSearchViewController?
Where do I use [self.navigationController popViewControllerAnimated:YES];
as the view continues there, and ViewDidUnload is never called.
My idea was that this should be handle in the first ViewController, the HomeViewController but I have no idea what is the method I should hook to, and I read the documentation and I can't figure it out :-/
Any help is greatly appreciated, thank you.
HomeViewController
alt text http://cl.ly/XNS/Screen_shot_2010-04-21_at_22.38.51.png
SimpleSearchViewController
alt text http://cl.ly/YDw/Screen_shot_2010-04-21_at_22.40.00.png
SimpleSearchViewController after pressing the Back button
alt text http://cl.ly/XLO/Screen_shot_2010-04-21_at_22.40.21.png
To add the image from a comment that asks if HomeViewController as the root controller for the NavigationViewController
Not sure if this helps but when implementing navigationItem in code, if you don't call the super the popping functionality will not be present
-(UINavigationItem*) navigationItem
{
UINavigationItem* item = [super navigationItem];
item.title = #"search";
return item;
}