Set UIAlertView delegate - ios

I try to have the delegate method called but it isn't. What should I change in my code? Thank you.
I tried to add in Class1.m:
+(void)popupAlert:(NSString*)msg tag:(NSInteger)tag{
Class1 *c= [[Class1 alloc]init];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#""
message:msg
delegate:c (I also tried c.self)
cancelButtonTitle:...
otherButtonTitles:...,nil];
alert.tag=tag;
[alert show];
}
I try to set alertview delegate to make this delegate method called.
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
Here is what I'm doing:
Class1.h:
+(void)popupAlert:(NSString*)msg tag:(NSInteger)tag;
Class1.m:
+(void)popupAlert:(NSString*)msg tag:(NSInteger)tag{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#""
message:msg
delegate:self
cancelButtonTitle:...
otherButtonTitles:...,nil];
alert.tag=tag;
[alert show];
}
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
//some coding
}
Class2.m:
-(void)func1{
[Class1 popupAlert:#"blah blah" tag:0];
}

It seems c gets dealloced right after [alert show]; because there are no strong reference pointing to this object afterwards and the delegate becomes nil;
In other example you should turn instance method
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
to class method:
+(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex

Rethink your architecture.
You are creating the alert in a class method. (That is indicated by the leading + instead of -). Within that self is a reference to the class, not the object.
alertView:didDismissWithButtonIndex: is an instance method. I am not even sure that you could apply a delegate protocol to the class instead of the instances. But if you can, then your delegate method would have to be a class method too.
+(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
Well, I am just thinking of that and DO NOT PROMISE that it works that way.
If I were you I'd go for a singleton pattern and use instance methods to throw the alert and to respond to the delegate protocol.
Anyway, I am wondering which warning xcode displays on delegate:self and why you are not telling us about the warning. Warnings are there for a reason.

Alertview delegate property is week reference.
So once you finished the +(void)popupAlert:(NSString*)msg tag:(NSInteger)tag method then all local variables on Stack will removed from memory.
means destroyed. So even you set the delegate there it wont work.
#property(nonatomic,assign) id /*<UIAlertViewDelegate>*/ delegate;
So you should do like this
-(void)func1{
Class1 *class1 = [[Class1 alloc] init];
[Class1 popupAlert:#"blah blah" tag:0 withDelegate:class1];
}
+(void)popupAlert:(NSString*)msg tag:(NSInteger)tag withDelegate:(id)delegateOfAlert]{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#""
message:msg
delegate:delegateOfAlert
cancelButtonTitle:...
otherButtonTitles:...,nil];
alert.tag=tag;
[alert show];
}

Related

UIAlertview clicked button at index delegate method not being called

Am new to AlertViews with actions. Have set mine up as in the examples I found here including setting the delegate method in my .h, but when I debug find that it is not reaching my clickedButtonAtIndex method. Probably missing something simple :-/ Any help solving this would be appreciated, thanks.
Here's my code:
.h file
#interface LineDetailViewController : UIViewController <UIAlertViewDelegate>
. m file:
- (IBAction)removeLineButton:(UIButton *)sender {
NSString * requestSubmitText = [NSString stringWithFormat:#"Hey Bro are you sure you want to remove this line you created, it will also remove all the reviews attached and can not be undone?"];
UIAlertView *removeLineRequest = [[UIAlertView alloc] initWithTitle:#"WARNING!!"
message:requestSubmitText
delegate:nil
cancelButtonTitle:#"Remove It"
otherButtonTitles:#"Cancel",nil];
[removeLineRequest show];
- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex{
//if (buttonIndex == [alertView cancelButtonIndex]){
if (buttonIndex == 0){
NSLog(#"Cancel button pressed");
}else{
NSLog(#"other button pressed");
}
}
You have to set delegate to self
UIAlertView *removeLineRequest = [[UIAlertView alloc] initWithTitle:#"WARNING!!"
message:requestSubmitText
delegate:self // <- here
cancelButtonTitle:#"Remove It"
otherButtonTitles:#"Cancel",nil];
Call removeLineRequest.delegate = self.
While creating your alert view set your delegate to self . And you have already implemented the UIAlertViewDelegate.
To solve your problem, just set the delegate to self instead of nil.
Some additional info,
UIAlertView and UIAlertViewDelegate have been deprecated. As per the documentation,
UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead.
Relevant tutorial here

UIAlertView crashes when button tapped: how to solve?

I have a class that I instance to show an alert view like this:
- (void)showAlert
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Do you want to try again?"
message:nil
delegate:self
cancelButtonTitle:#"Yes"
otherButtonTitles:#"No", nil];
[alertView show];
}
}
I need self to be the delegate because I need alertView:didDismissWithButtonIndex: to be called to perform some actions when the user taps the alert view's button. This usually works well, but from time to time, I get this crash:
SIGSEGV
UIKit-[UIAlertView(Private) modalItem:shouldDismissForButtonAtIndex:]
I guess this is because the delegate, for any reason, was released, right? Or is this because what was released was the alert view? How could I solve this? I need the alert view to have a delegate, and I've reading several related posts and I couldn't find an answer that fits my scenario.
I'm testing in iOS 7.0, I don`t know if that could have to do with the issue.
Thanks in advance
It seems that you tap alert when its delegate is released:
delegate:self
It happens because UIAlertView delegate property is of assign type (not weak!).
So your delegate potentially can point to released object.
Solution:
in dealloc method you need to clear delegate for your alertView
- (void)dealloc
{
_alertView.delegate = nil;
}
But before you need to make iVar _alertView and use it for your alertViews
- (void)showAlert
{
_alertView = ...;
[_alertView show];
}
Update your code as follows:
- (void)showAlert {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Do you want to try again?"
message:nil
delegate:self
cancelButtonTitle:#"Yes"
otherButtonTitles:#"No", nil];
[alertView show];
}
Its due to you are missing the nil for otherButtonTitles part.
Missing sentinel in method dispatch warning will be shown if you didn't add nil.
That's because the alertView's delegate object released while clicking the button. I think it's a bug of SDK:
#property(nonatomic,assign) id /*<UIAlertViewDelegate>*/ delegate; // weak reference
should be:
#property(nonatomic, weak) id /*<UIAlertViewDelegate>*/ delegate; // weak reference
To fix the issue:
add a weak delegate for UIAlertView using association.
swizzle the init, setDelegate: delegate methods, set alertView delegate to self, set step 1 weak delegate with the param delegate.
implement all delegate methods, deliver the methods using the weak delegate.

UIAlertView dismissal in utility class

In my application i want alertview in many views.So what i did is just wrote a single alertview in a utility class and use it everywhere.This is working fine.
I even tried by setting <UIAlertViewDelegate> but in vain.
Utility Class
#interface SSUtility: NSObject<UIAlertViewDelegate> {
}
+(void)showAllert;
#end
#implementation SSUtility
+(void)showAllert{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"gotoappAppstore",#"") message:#"" delegate:self cancelButtonTitle:NSLocalizedString(#"Ok",#"") otherButtonTitles:nil];
[alert show];
[alert release];
}
#end
Now from my view
-(void)pressButton{
[SSutility showAllert]
}
Now i want to give a button action for alert view click and call a method on that button action.
So im stuck with,in which class i want to implement this method.I tried it in utility class and viewc controller but the method is not getting triggered when "ok" button is pressed.
-(void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
Can anyone please help me on this?
Thanks in advance.
You wire the alert view button response method by setting your alert view object delegate usually to the owner object and implementing the – alertView:clickedButtonAtIndex: method.
You need 4 parts in your code:
instantiate your UIAlertView object
send show message to your UIAlertView object
set delegate
implement the delegate method
Example:
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"myTitle" message:#"myMessage" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitle:#"Another button"];
[myAlertView setDelegate:self];
[myAlertView show];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) //index 0 is cancel, I believe
{
// code for handling cancel tap in your alert view
}
else if (buttonIndex == 1)
{
// code for handling button with index 1
}
}
I would recommend you get more familiar with how delegates work. This'll come back again a lot.
You set delegate:nil in your UIAlertView's init.
You should set to delegate:self, like this:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"gotoappAppstore",#"") message:#"" delegate:self cancelButtonTitle:NSLocalizedString(#"Ok",#"") otherButtonTitles:nil];
in order to use the delegate in the same class (a.k.a. self).
As a sidenote, if you use Automatic Reference Counting (ARC), you do not need [alert release] (your Xcode compiler should warn you about this)

Which button on my UIAlertView did the user press?

I've created a UIAlertView and now I want to check which button the user presses.
My code is:
- (IBAction)button1 {
{
UIAlertView *alert1 = [[UIAlertView alloc] init];
[alert1 setTitle:#"Hello"];
[alert1 setMessage:#"Do you like smoking?"];
[alert1 addButtonWithTitle:#"Yes"];
[alert1 addButtonWithTitle:#"No"];
[alert1 show];
}
}
How can I check it with if-else statement?
You must set the delegate of your UIAlertView to the class that will handle the callbacks from the UIAlertView itself
E.g.
[alert1 setDelegate:self];
Where self is your current UIViewController that implements the protocol <UIAlertViewDelegate>.
When the user taps a button, the UIAlertView will call back to whatever object you set as the delegate, in my example we are using the UIViewController that created the UIAlertView. Once we get the callback, we can check which button index has been tapped and act accordingly. This is a basic delegation pattern that is used throughout iOS development, especially UIKit.
Example
#interface MyViewController : UIViewController() <UIAlertViewDelegate>
#end
#implementation MyViewController
- (IBAction)button1 {
{
UIAlertView *alert1 = [[UIAlertView alloc] init];
[alert1 setTitle:#"Hello"];
[alert1 setMessage:#"Do you like smoking?"];
[alert1 addButtonWithTitle:#"Yes"];
[alert1 addButtonWithTitle:#"No"];
[alert1 setDelegate:self];
[alert1 show];
}
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// Handle interaction
switch (buttonIndex)
{
case 0:
NSLog(#"Yes was pressed");
break;
case 1:
NSLog(#"No was pressed");
break;
}
}
#end
It is very important you specify in the header file, or class interface extension that your class implements the <UIAlertViewDelegate>.
I recommend you see the UIAlertViewDelegate Protocol Reference for more information, and you can follow this approach for many other UIKit components.
Implement UIAlertViewDelegate protocol in your view controller, set it as a delegate to the UIAlertView, and wait for the alertView:clickedButtonAtIndex: event, like this:
#interface MyViewController : UIViewController <UIAlertViewDelegate>
-(void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex;
#end
#implementation MyViewController
-(void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(#"Button %d clicked...", (int)buttonIndex);
}
#end
Change the code that displays the alert view as follows:
UIAlertView *alert1 = [[UIAlertView alloc] init];
[alert1 setTitle:#"Hello"];
[alert1 setMessage:#"Do you like smoking?"];
[alert1 addButtonWithTitle:#"Yes"];
[alert1 addButtonWithTitle:#"No"];
alert1.delegate = self; // <<== Add this line
[alert1 show];
Adding on to the answer by Jeff, I think that you have to enable the other button in order to place your logic when the button is clicked.
In order to creating the button with your code:
- (IBAction)button1
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hello"
message:#"Do you like smoking?"
delegate:self
cancelButtonTitle:#"Yes"
otherButtonTitles:#"No", nil];
[alert show];
}
But before knowing which button is clicked, you have to enable the first other button, by calling this delegate method:
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
return YES;
}
This will enable the NO button that you have created. Then, you will be able to do some logic with the clickedButtonAtIndex method, which I suppose you will be doing.
Implement the UIAlertView delegate method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
// i love smoking!
} else if (buttonIndex == 1) {
// i hate smoking!
}
}
Be sure to declare the UIAlertViewDelegate in your header class.
Make sure that the alertViewShouldEnableFirstOtherButton: method returns YES, if not you will not be able to put in your logic for when the button is pressed.
Hope this helps! :)
The best thing you can do is make the class that presents your alert view conform to the UIAlertViewDelegate protocol and implement the method –alertView:clickedButtonAtIndex:. That way you'll know what button was clicked.
Hope this helps!

UIAlertView in appdelegate.m does not work

I have been googling this problem for almost a whole day now, without getting any closer to a solution, so i would like to ask you guys.. :)
I'm working on an iOS app, which should connect to a mbed over WiFi and give the user a dialog if it connects and if it doesn't and if not, then give the user the possibility to retry.
My problem is now that i have implemented the connecting method in appdelegate.m and it is from here I would like to show the alerts..
The alerts it self works fine, but I have problems detecting when a button is pressed, the clickedButtonAtIndex is not being called.
I have added the UIAlertViewDelegate in the appdelegate.h, like so:
#interface AppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate, UIAlertViewDelegate>
and have set the delegate to self, in the alertview, like so:
alert_NOT = [[UIAlertView alloc] initWithTitle:#"Not connected!" message:message_to_user delegate:self cancelButtonTitle:#"Try again" otherButtonTitles: nil];
[alert_NOT show];
[alert_NOT release]
and the clickedButtonAtIndex looks like
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(#"test");
}
So I would love to see the word "test" in the log when a button is pressed in the alertview, but nothing happens.
Update:
Tried implementing it in my "FirstViewController.m" and there it works :S but I would very much like to have it in the appdelegate.m if possible..
I'm currently looking into a similar implementation and would like to share an idea I had with you: perhaps using an NSNotification that fires when your delegate's conditions are met, which can be listened for in your VC(s) and handled appropriately, with an alert view, at the top of the stack.
#interface urAppDelegate : NSObject <UIApplicationDelegate,UIAlertViewDelegate>
If you synthesized the alert_not then use it like this with self:
self.alert_NOT = [[UIAlertView alloc] initWithTitle:#"Not connected!" message:message_to_user delegate:self cancelButtonTitle:#"Try again" otherButtonTitles: nil];
[alert_NOT show];
[alert_NOT release];
You should use the alertViewCancel method for this.
- (void)alertViewCancel:(UIAlertView *)alertView
{
NSLog(#"text");
}
Define as below:
#define appDelegate ((AppDelegate*)[UIApplication sharedApplication].delegate)
and alert as:
UIAlertView *alert_NOT = [[UIAlertView alloc] initWithTitle:#"Not connected!" message:message_to_user delegate:appDelegate cancelButtonTitle:#"Try again" otherButtonTitles: nil];
[alert_NOT show];
Here set delegate as defined keyword, i.e., appDelegate.
Hope this helps.

Resources