Linking UIActionSheet buttons with a current IBAction - iphone

I have got created a UIActionsheet programatically however I can't figure out how to link it to an existing IBAction.
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
self.label.text = #"Destructive Button Clicked";
}}
This is my code where i click on a button and I want it to link to the following IBAction that i have already got.
- (IBAction)doButton;
So, how would i go about linking this? Any help would be greatly appreciated.
Thanks

-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex: (NSInteger)buttonIndex {
if (buttonIndex == 0) {
self.label.text = #"Destructive Button Clicked";
[self doButton];
}
}

The best way to do it is to add a UIActionSheetDelegate to your class and call the action sheet in your IBAction.
.h file
#interface ViewController : UIViewController <UIActionSheetDelegate>
-(IBAction)doButton;
#end
.m file
-(IBAction)doButton {
UIActionSheet *doSheet = [[UIActionSheet alloc] initWithTitle:#"Your title" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Button 0", #"Button 1", nil];
[doSheet showInView:self.view];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex: (NSInteger)buttonIndex {
if (buttonIndex == 0) {
//Do Something
}
if(buttonIndex == 1) {
//Do Something else
}
}

Related

UITableView Edit Mode Add the cell defined by user?

I wanted to use the table editing mode so that the users can choose which Cells to add.
For eg I have
addArray = {#"Red",#"Blue",#"Green"};
Now , what I want is that when user enters the editing mode and presses the add button, he gets the options: Red,Blue,Green and selects the cell to be added.
-(IBAction)addButtonPressed
{
[displayArray addObject:"User's Choice"];
[self.tableview reloadData];
}
You probably want to use a UIActionSheet (see Apple docs):
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Select an option"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Red", #"Green", #"Blue", nil];
[actionSheet showInView:self.view];
You will need to make your view controller conform to the UIActionSheetDelegate protocol:
#interface MyViewController : UITableViewController <UIActionSheetDelegate>
Then, implement the actionSheet:clickedButtonAtIndex: method in your view controller:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == actionSheet.firstOtherButtonIndex) {
// Red
[displayArray addObject:"Red"];
[self.tableview reloadData];
}
else if (buttonIndex == actionSheet.firstOtherButtonIndex + 1) {
// Green
[displayArray addObject:"Green"];
[self.tableview reloadData];
}
else if (buttonIndex == actionSheet.firstOtherButtonIndex + 2) {
// Blue
[displayArray addObject:"Blue"];
[self.tableview reloadData];
}
}

is there easy way to handle UIAlertView result without delegation?

I have a function that shows a UIAlertView with YES/NO buttons, and it is used only inside the function's scope so I dont want to implement a delegation to catch the user feedback.
Is there any way to know what button users clicked without implement UIAlertViewDelegate, something like:
[alert show];
if([alert indexOfClickedButton] == indexOfYes)
{
....
}
Or lambda expression as in Animation
There is no way to avoid delegation completely, but you could create a wrapper to that effect along these lines:
#interface MyAlertViewDelegate : NSObject<UIAlertViewDelegate>
typedef void (^AlertViewCompletionBlock)(NSInteger buttonIndex);
#property (strong,nonatomic) AlertViewCompletionBlock callback;
+ (void)showAlertView:(UIAlertView *)alertView withCallback:(AlertViewCompletionBlock)callback;
#end
#implementation MyAlertViewDelegate
#synthesize callback;
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
callback(buttonIndex);
}
+ (void)showAlertView:(UIAlertView *)alertView
withCallback:(AlertViewCompletionBlock)callback {
__block MyAlertViewDelegate *delegate = [[MyAlertViewDelegate alloc] init];
alertView.delegate = delegate;
delegate.callback = ^(NSInteger buttonIndex) {
callback(buttonIndex);
alertView.delegate = nil;
delegate = nil;
};
[alertView show];
}
#end
(ARC is assumed, if you are not using it change delegate = nil to [delegate release].)
Usage would be something like:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Confirm" message:#"Yes or No?" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"Yes",#"No", nil];
[MyAlertViewDelegate showAlertView:alert withCallback:^(NSInteger buttonIndex) {
// code to take action depending on the value of buttonIndex
}];
I have written a blog post about how to (and why) add block callbacks to alert views, action sheets and animations:
http://blog.innovattic.com/uikitblocks/
If you just want a working implementation of this you can download the sources files from GitHub:
https://github.com/Innovattic/UIKit-Blocks
Usage:
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"My easy alert"
message:#"Would you like to perform some kind of action?"
cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", nil];
[alert setHandler:^(UIAlertView* alert, NSInteger buttonIndex) {
NSLog(#"Perform some kind of action");
} forButtonAtIndex:[alert firstOtherButtonIndex]];
[alert show];
It's very easy. Say you have an alert, something like this:
//Alert
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Confirm" message:#"Yes or No?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Yes",#"No", nil];
[alert show];
You're going to need to add this method:
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
A possible implementation of this method would look like this:
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
//Checks For Approval
if (buttonIndex == 1) {
//do something because they selected button one, yes
} else {
//do nothing because they selected no
}
}
You can do this using custom view which can be hidden and shown to avoid ActionSheets
UIView *AlertVw=[UIView alloc]initWithFrame:CGRect(x,y,w,h)]];
UIButton *SaveButton=[UIButton alloc]initWithFrame:CGRect(x,y,w,h)]];
[CustomButton setTitle:#"Ok" forState:UIControlStateNormal];
[SaveButton addTarget:self action:#selector(SaveClicked) forControlEvents:UIControlEventTouchUpInside];
UIButton *CancelButton=[UIButton alloc]initWithFrame:CGRect(x,y,w,h)]];
[CustomButton setTitle:#"Cancel" forState:UIControlStateNormal];
[CancelButton addTarget:self action:#selector(CancelClicked) forControlEvents:UIControlEventTouchUpInside];
[AlertVw addSubview:SaveButton];
[AlertVw addSubview:CancelButton];
[self.view addSubview:AlertVw];
-(void)SaveButton
{
//Code to apply on Save clicked
[AlertVw removeFromSuperView]; //Also you can use AlertView.hidden=YES;
}
-(void)CancelButton
{
//Code to apply on cancel clicked
[AlertVw removeFromSuperView]; //Also you can use AlertView.hidden=YES;
}
No need to derive the class. With Block, it is easy to get user selected button index.
typedef void(^AlertViewCallBackBlock)(NSInteger selectedIndex);
#interface ABC ()
#property (nonatomic, copy) AlertViewCallBackBlock alertViewBlock;
#end
#implementation
- (void)showAlert {
self.alertViewBlock = ^(NSInteger selectedIndex) {
if (selectedIndex == 1) {
}
};
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Confirm" message:#"Yes or No?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Yes",#"No", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
self.alertViewBlock(buttonIndex);
}
#end
Thanks Arkku. Here is the Swift version.
https://github.com/exchangegroup/alert-view-with-callback-swift
let alertView = UIAlertView(...)
AlertViewWithCallback().show(alertView) { alertView, buttonIndex in
println("You closed alert by tapping button #\(buttonIndex)")
}
UIAlertView is deprecated from iOS 8.0, a better solution will be using UIAlertController:
let alert = UIAlertController(title: "message", message: "Title", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "YES", style: .Default, handler: { (action) -> Void in
// Action for YES
}))
alert.addAction(UIAlertAction(title: "NO", style: .Default, handler: { (action) -> Void in
// Action for NO
}))
self.view.window!.rootViewController!.presentViewController(alert, animated: true, completion: nil)

Multiple UIActionSheets on the same delegate

I'm writing a puzzle game. When the user presses the check button, I see if the solution they entered is correct. Depending on the result, I present one of two action sheets for them. For now I just have some NSLog statements to make sure things are getting called, but only one of the sheets seems to work properly.
Nothing gets called when I click a button in showErrorsActionSheet. The action sheet disappears off the screen, but the logs never print.
I suspect it has something to do with having two actionsheets declared to the same delegate (self)
- (void) checkSolution {
//code determines the value of the BOOL allCorrect
if (allCorrect) { //IF ALL OF THE LETTERS WERE CORRECT
//display UIAlertView;
NSLog(#"allCorrect");
UIActionSheet *levelCompleteActionSheet = [[UIActionSheet alloc] initWithTitle:#"Congratulations! You Have Finished the Level!" delegate:self cancelButtonTitle:#"Review my work" destructiveButtonTitle:#"Choose next puzzle" otherButtonTitles:nil, nil];
[levelCompleteActionSheet showInView:self.view];
[levelCompleteActionSheet release];
}
else {
//[self showIncorrectLettersInRed];
UIActionSheet *showErrorsActionSheet = [[UIActionSheet alloc] initWithTitle:#"Sorry, thats not right. Show errors in red?" delegate:self cancelButtonTitle:#"No Thanks, I'll keep trying" destructiveButtonTitle:#"Yes please, I'm stuck!" otherButtonTitles:nil, nil];
[showErrorsActionSheet showInView:self.view];
[showErrorsActionSheet release];
}
}
the methods that are supposed to be called are:
- (void) levelCompleteActionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex != [actionSheet cancelButtonIndex]) {
NSLog(#"return to levelSelect");
//pushViewController:levelSelect
}
else {
NSLog(#"continue to examine solution");
}
}
- (void) showErrorsActionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex != [actionSheet cancelButtonIndex]) {
NSLog(#"show errors in red");
}
else {
NSLog(#"continue to try");
}
}
and Ive declared the UIActionSheet protocol in the interface file as follows:
#interface GamePlay : UIViewController <UIActionSheetDelegate> {
Set a tag for each actionSheet, then use a switch statement in the UIActionSheet delegate.
Assign a tag
- (void)checkSolution
{
if (allCorrect)
{
UIActionSheet *levelCompleteActionSheet = [[UIActionSheet alloc] initWithTitle:#"Congratulations! You Have Finished the Level!" delegate:self cancelButtonTitle:#"Review my work" destructiveButtonTitle:#"Choose next puzzle" otherButtonTitles:nil, nil];
[levelCompleteActionSheet setTag: 0];
[levelCompleteActionSheet showInView:self.view];
[levelCompleteActionSheet release];
}
else
{
UIActionSheet *showErrorsActionSheet = [[UIActionSheet alloc] initWithTitle:#"Sorry, thats not right. Show errors in red?" delegate:self cancelButtonTitle:#"No Thanks, I'll keep trying" destructiveButtonTitle:#"Yes please, I'm stuck!" otherButtonTitles:nil, nil];
[showErrorsActionSheet setTag: 1];
[showErrorsActionSheet showInView:self.view];
[showErrorsActionSheet release];
}
}
UIActionSheet Delegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch ( actionSheet.tag )
{
case 0: /* levelCompleteActionSheet */
{
switch ( buttonIndex )
{
case 0: /* 1st button*/
break;
case 1: /* 2nd button */
break;
}
}
break;
case 1: /* showErrorsActionSheet */
break;
}
}
The same would apply anywhere else in this class as well, including levelCompleteActionSheet: and showErrorsActionSheet:. The only difference is, you would need to create an iVar for each actionSheet instead of creating them in checkSolution.
The methods that will be called by a UIActionSheet on its delegate are the methods listed in the UIActionSheetDelegate protocol.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIModalViewDelegate_Protocol/UIActionSheetDelegate/UIActionSheetDelegate.html
To be called, your method must be one of those methods. I don't see levelCompleteActionSheet or showErrorsActionSheet listed in that protocol! :) Your method must be named actionSheet:clickedButtonAtIndex:, and not some name you make up out of whole cloth.
Using Tag solve this problem
levelCompleteActionSheet.tag = 100;
showErrorsActionSheet.tag = 101;
- (void) levelCompleteActionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if(actionSheet.tag == 100){
// levelCompleteActionSheet implement your required function
}
else if(actionSheet.tag == 101){
// showErrorsActionSheet implement your required function
}
}

UIAlertView Button Event Problem

alright so i have a small problem here, i have this here.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
//YES clicked ...do your action
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
else if (buttonIndex == 1)
{
//NO clicked
return;
}
}
This Allows me to capture events triggered from UIAlertView Buttons but i have assigned it a value and on the same page i need another value to be assigned to that class so:
if(buttonIndex == 2){//Proceed}
i mainly want it so that when the button is pushed on my second alert it will go back to the processes it was doing and not proceed with the event of (buttonIndex == 0).
So Does anyone know Where i could start?
Just store a reference in you .h file of the 2 UIAlertView's, and then do a check. For instance, in your .h file:
UIAlertView * alertView1;
UIAlertView * alertView2;
In your .m file, set up your UIAlertView's in you viewDidLoad method, and change the alertView:clickedButtonAtIndex: method to:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex; {
if (alertView == alertView1) {
// Do what you want the alertView1 to do here.
if (buttonIndex == 0) {
//YES clicked ...do your action
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
else if (buttonIndex == 1) {
}// etc.
}
else if (alertView == alertView2) {
// Do what you want the alertView2 to do here.
}
}
Hope that Helps!
Something else you can do is use the alertView tag in case you have multiple alertviews in your app. For instance, you could do something like this:
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:#"Title" message:#"AThe message." delegate:self cancelButtonTitle:#"button 1" otherButtonTitles: #"button 2", nil];
alert1.tag = 0;
[alert1 show];
[alert1 release];
Then in your delegate method, simply put the following if clause:
if (alertView == alertView1)
before your code above.
If you don't figure this out, you could place a counter in the program that counts the number of times the alertview had been triggered, and then act upon that value.

UIAlertView easy way to tell if cancel button is selected

I know I've done this before but I just can't figure it out again.
What is the method I would use to see if a cancel button was pressed. I don't want to do it based on the button index. There is a way to do it, something like:
[alertView isCancelIndex:index];
Anyone know?
The UIAlertView has a property of cancel button index
#property(nonatomic) NSInteger cancelButtonIndex
Usage
[alertView cancelButtonIndex]
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == [alertView cancelButtonIndex]) {
NSLog(#"The cancel button was clicked for alertView");
}
// else do your stuff for the rest of the buttons (firstOtherButtonIndex, secondOtherButtonIndex, etc)
}
In the delegate of UIAlertView is the method
(void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex
And then:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSInteger cancelIndex = [alertView cancelButtonIndex];
if (cancelIndex != -1 && cancelIndex == buttonIndex)
{
// Do something...
}
}