Prevent from UIAlertView to repeat when click on tableViewCell - objective-c

I'm kinda stuck with a stupid problem, in my app when a user press on a TableViewCell he can change some value in the server, before i am sending the information to server i want to show UIAlertView to the user to make sure he wants to do that.
so in didSelectRowAtIndexPath:
i wrote this
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Caution!" message:#"bla bla " delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
[alert show];
then its calls the UIAlertView method clickedButtonAtIndex:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
NSString *url = #"some url";
NSDictionary *paramerter = #{#"parameter":parameter};
[self.jsonHandler startParseWithParameters:paramerter andUrlAdress:url withCompletion:^(int errValue) {
if (errValue == 1) {
NSLog(#"ERROR");
}else if (errValue == 0){
[self AlertViewWithTitle:#"success" andMessage:#"success"];
}
}];
}
}
the problem is that the if (buttonIndex == 0) called for every cell and change them all!
and i get UIAlertView message for every cell in the tableView.
how can i prevent it?
EDIT
Ok the problem caused because i use the same buttonIndex for both UIAlertViews
i solved it using this:
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"buttonString"]){
//Do what ever you need
}
hope someone find it helpful.

Related

Two Alertviews on one view [duplicate]

This question already has answers here:
Two Alert Views in One View Controller - buttonIndex Response
(4 answers)
Closed 7 years ago.
EDIT:
Problem Solved ==> Simply giving a tag solved the problem.
I have the following problem:
On a view I have two UIalertviews:
NSString *message = [NSString stringWithFormat:#"Users must enter this code to join the meeting: %#", meetingCode];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Meeting code"
message:message
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:#"Copy to clipboard", nil];
[alert show];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == [alertView cancelButtonIndex])
{
NSLog(#"Code not copied");
}
else
{
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = meetingCode;
NSLog(#"Code copied");
}
}
and this one:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
AgendaModel* agenda = _meeting.agenda[indexPath.row] ;
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:agenda.id,#"id",agenda.name,#"name", nil];
NSString *message = [NSString stringWithFormat:#"Are you sure that you want to delete : %#?", agenda.name];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:message
delegate:self
cancelButtonTitle:#"Close"
otherButtonTitles:#"Delete", nil];
[alert show];
NSString *delete_url = [NSString stringWithFormat:#"RestAgendas/delete.json"];
[_meeting.agenda removeObject:agenda];
[self.tableView deleteRowsAtIndexPaths:[NSMutableArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[JSONAPI getWithPath:delete_url andParams:dict completion:^(id json, JSONModelError *err) {
NSLog(#"%#", json);
}];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == [alertView cancelButtonIndex])
{
NSLog(#"Agenda Won't Be Deleted");
}
else
{
NSLog(#"Agenda Will Be Deleted");
}
}
Now is the problem that I got the error: Duplicate declaration of method 'alertView:clickedButtonAtIndex'
How can I fix this? I tried some stuff I found here but I still can't make it work. Can someone help me?
Yep, like you said, giving a tag allows you to have multiple UIAlertView in one single view.
Same goes for UIActionSheet or UIAlertController
for future reference, even though this is probably a duplicate, simply create your alert like usual and add
myAlert.tag = 123; //any number of your choice
and in alertView:clickedButtonAtIndex
you can find it using a switch or some if's
if (alertview.tag = 123){
// this is my alert
}else if(alertview.tag = 333){
// this is my other alert
}
For what it's worth, I suggest using else if and not just if to avoid the whole method to be read everytime, and order your if's by decreasing likeliness of being called.
Note you can also give tags to buttons, views, cells, labels, and just pretty much every outlet you can find.

UIAlertView buttonIndex not working

I guess I'm missing something obvious. I have UIAlertView to get app review but I can't get the buttons to do anything. I've called the UIAlertViewDelegate in my.h, I also have anther UIAlertview which is just on an IBAction btn and that works fine although it just had cancel btn.
I tried giving alert.tag = 1 but that never made any difference so I commented out my first UIAlertview, so I just have one alert, still no joy. I guess I am missing something simple.
I've also tried alertview.cancelButtonIndex or alertview.firstOtherButtonIndex instead of 0
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog(#"index 0 ");
}
else if (buttonIndex == 1) {
NSLog(#"index 1 ");
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"www.google.com"]];
NSUserDefaults *rateApp = [NSUserDefaults standardUserDefaults];
NSInteger appLaunch = [ rateApp integerForKey:#"appLaunch"];
appLaunch = 0 ;
[rateApp setInteger: appLaunch forKey:#"appLaunch"];
}
else if (buttonIndex == 2) {
NSLog(#"index 2 ");
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
//rate app appLaunch == 5 || appLaunch ==10
NSUserDefaults *rateApp = [NSUserDefaults standardUserDefaults];
NSInteger appLaunch = [ rateApp integerForKey:#"appLaunch"];
if (appLaunch == 1 ) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Like this app ?" message:#"Why not rate at the app store" delegate:nil cancelButtonTitle:#"No thanks" otherButtonTitles:#"Yes",#"Remind me later", nil];
// alert.tag = 1;
[alert show];
}
Thanks for any help.
AlertView's delegate should be self instead of nil, if you want to invoke its delegate method.
Use this Code :
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Like this app ?"
message:#"Why not rate at the app store"
delegate:self
cancelButtonTitle:#"No thanks"
otherButtonTitles:#"Yes",#"Remind me later", nil];

The UIButton not responding as it should in single-view app in iOS6

The selector 'go' with IBAction return type is not responding correctly. If the button is clicked with the text field being empty i.e its value being nil , the flow should return the 'if' part and not 'else'. But it works fine when I click the button second time. what can be the problem ?
Below is the code from implementation file i.e. ViewController.m where I have implemented the go selector.
#synthesize textField = _textField;
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
//Clear the text field
self.textField.text =nil;
}
NSString *s;
-(IBAction)go:(id)sender
{
[self.textField resignFirstResponder];
if (self.textField.text == nil)
{
s = [NSString stringWithFormat:#" Enter Your Name First " ];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Blank Field : "
message:s
delegate:self
cancelButtonTitle:#"OKAY"
otherButtonTitles:nil];
[alert show];
}
else
{
s = [NSString stringWithFormat:#"Hello %# " , self.textField.text];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hello "
message:s
delegate:self
cancelButtonTitle:#"Thanks"
otherButtonTitles:nil];
[alert show];
}
}
Please help.
Thanks in advance.
Instead of using nil as your comparator I would instead use something more concrete like
if ([self.textfield.text length] > 0)
{
}
else
{
}

Basic use of UIAlertView causes EXC_BAD_ACCESS

I'm implementing a very simple iOS application just to practice showing a pop up alert in, and I get an error when I press the alert button:
Thread 1:EXC_BAD_ACCESS(code=1,address=0x676f6f57)
This is the code:
- (IBAction)AlertButton {
alert = [[UIAlertView alloc]
initWithTitle:#"Alert" message:#"Alert"
delegate:self
cancelButtonTitle:#"Dismiss"
otherButtonTitles:#"Apple", "Google" ,nil];
[alert show];}
-(void)alertView :(UIAlertView *)alertView clickedButttonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex == 1){
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:#"http://apple.com"]];
}
if(buttonIndex == 2){
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:#"http://google.com"]];
}}
the problem is with the constructor of the UIAlertView, in the line:
otherButtonTitles:#"Apple", "Google" ,nil];
your forget the # before "Google". And finally change:
-(void)alertView :(UIAlertView *)alertView clickedButttonAtIndex:(NSInteger)buttonIndex{
by
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
The real problem is you miss an # in front of "Google", so it is not an NSString and hence the crash.
use this
.h
no need for IBOutlet.just
UIAlertView *alert;
.m
alert = [[UIAlertView alloc]
initWithTitle:#"Alert"
message:#"Alert"
delegate:self
cancelButtonTitle:#"Dismiss"
otherButtonTitles:#"Apple", #"Google", nil
];

How to write event handlers for buttons in UIAlertView?

Say I have a alert view like follows in obj c
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"title" message:#"szMsg" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:#"download"];
[alert show];
[alert release];
Now we have 2 buttons on the alert view (Ok & Download), how to write an event handler for the Download one?
First you will need to add the UIAlertViewDelegate to your header file like below:
Header file (.h)
#interface YourViewController : UIViewController<UIAlertViewDelegate>
Implementation File (.m)
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"title" message:#"szMsg" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:#"download"];
[alert show];
[alert release];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
//Code for OK button
}
if (buttonIndex == 1)
{
//Code for download button
}
}
Now that most iOS devices have firmare versions with blocks support it’s an anachronism to use the clumsy callback API to handle button presses. Blocks are the way to go, see for example the Lambda Alert classes on GitHub:
CCAlertView *alert = [[CCAlertView alloc]
initWithTitle:#"Test Alert"
message:#"See if the thing works."];
[alert addButtonWithTitle:#"Foo" block:^{ NSLog(#"Foo"); }];
[alert addButtonWithTitle:#"Bar" block:^{ NSLog(#"Bar"); }];
[alert addButtonWithTitle:#"Cancel" block:NULL];
[alert show];
Declare your UIAlertViews as known.
UIAlertView *alertLogout=[[UIAlertView alloc]initWithTitle:#"Title" message:#"Stop Application?" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes",nil];
[alertLogout show];
[alertLogout release];
set delegate to self and implement this method.
-(void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if(actionSheet== alertLogout) {//alertLogout
if (buttonIndex == 0){
}else if(buttonIndex==1){
}
}else if (actionSheet==alertComment) {//alertComment
if (buttonIndex==0) {
}
}
}
Stack's and Guillermo Ortega's answer is probably what you would use with a couple of UIAlertView but not for ten. I use to use BlocksKit which is kind of the same as Lambda stuff which is what soul suggested. That is a good option too, although if you have too many nested blocks you will start seeing the demerits of it (Aside from the fact you will be relying in another library).
The usual way of handling several stuff would be to have a handler object. (
#interface MyAlertViewDelegate : NSObject <UIAlertViewDelegate> #end) make that object the delegate of the alert view and make sure the object is alive at least until the alert view is dismissed.
This will certainly work, but could be too much work...
What follows is what I came up with; IMO it is simpler and there is no need of any thirdParty library, or an ivar per UIAlertView. Just one extra object (#property (nonatomic, strong) NSArray *modalActions) to store the actions the current UIAlertView will cause to perform
Showing an UIAlertView and reacting accordingly
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:alertTitle
message:#"Blah blah"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:b1, b2, b3, nil];
// Add one selector/action per button at the proper index
self.modalActions = #[
[NSNull null], // Because indexes of UIAlertView buttons start at 1
NSStringFromSelector(#selector(actionForAlertViewButton1)),
NSStringFromSelector(#selector(actionForAlertViewButton2)),
NSStringFromSelector(#selector(actionForAlertViewButton3))];
[alertView show];
The delegate method:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (alertView.cancelButtonIndex != buttonIndex) {
[self performModalActionAtIndex:buttonIndex];
}
}
The part that actually performs the action:
- (void)performModalActionAtIndex:(NSInteger)index
{
if (-1 < index && index < self.modalActions.count &&
[self.modalActions[index] isKindOfClass:[NSString class]]) {
SEL action = NSSelectorFromString(self.modalActions[index]);
NSLog(#"action: %#", self.modalActions[index]);
if ([self respondsToSelector:action]) {
// There is a situation with performSelector: in ARC.
// http://stackoverflow.com/questions/7017281/
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:action];
#pragma clang diagnostic pop
}
self.modalActions = nil;
}
Reusable for UIActionSheets too
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title
delegate:self
cancelButtonTitle:cancelButton
destructiveButtonTitle:nil
otherButtonTitles:button1, button2, button3, nil];
// Similarly, add one action per button at the proper index
self.modalActions = #[
NSStringFromSelector(#selector(actionForActionSheetButton1)),
NSStringFromSelector(#selector(actionForActionSheetButton2)),
NSStringFromSelector(#selector(actionForActionSheetButton3))];
The delegate method:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (actionSheet.cancelButtonIndex != buttonIndex) {
[self performModalActionAtIndex:buttonIndex];
}
}
Why this works:
This works because of two reasons:
First, I never present two UIAlertView that have a delegate at the same time. (IMO you should't, it doesn't look good). Second, because in my case (as 90% of the cases) the target of the actions is always the same object (in this case: self). Even if you don't meet above conditions you can even use this approach with some modifications:
If you show two or more UIAlerViews or UIActionSheets at the same time (possible in the iPad) Use a dictionary with to store one array of actions associated with a certain UIAlertView/UIActionSheet.
If the target of the actions is not self, they you need to store pairs (target and the action) in the array. (Something to simulate UIButtons addTarget:action:...).
In either case, for storing the target and/or UIActionSheet/UIAlertView [NSValue valueWithNonretainedObject:] should become handy :)
First of all you declare UIAlertViewDelegate in .h file after put below code in .m file
- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
{
//put button action which you want.
}
}
Implement the UIAlertViewDelegate and make use of the delegate method
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex == 0) {
// Do something
}
else {
// Do something
}
}
UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:#"Data Saved" message:#"Choose more photos" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:Nil];
[alertView show];
[alertView release];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex==0)
{
[self dismissModalViewControllerAnimated:YES];
}
}
in swift:
we can use this little block of code
let alert = UIAlertController(title: "Alert", message: "This is an alert message", preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: {(action:UIAlertAction) in print("This is in alert block")
})
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)