I have this custom created object called MyAlertView, I'm creating an instance of it like this:
MyAlertView *alertView2 = [[MyAlertView alloc] initWithTitle:#"TITLE" message:#"MESSAGE" delegate:self cancelButtonTitle:#"CANCEL" otherButtonTitles:nil, nil];
the initializer works just fine and initializes the object.
then I call this method:
[alertView2 show];
this is the method implementation in MyAlertView Class:
- (void)show {
[self.delegate willPresentAlertView:self];
[self.myWindow makeKeyAndVisible];
[self.delegate didPresentAlertView:self];
}
I set a breakpoint there but the method just don't get called.
why is that?
Related
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];
}
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)
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!
I have a delegate, which recives a message to delete a item with that item as an argument.
I want to show a confirmation AlertView, and then, if the users press Yes, i want to delete it.
So, what I have is
The delegate method that gets called:
- (void) deleteRecording:aRecording(Recording*)aRecording {
NSLog(#"Cancel recording extended view");
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: NSLocalizedString(#"Cancel recording",nil)
message: NSLocalizedString(#"Are you sure you want to cancel the recording?",nil)
delegate: self
cancelButtonTitle: NSLocalizedString(#"No",nil)
otherButtonTitles: NSLocalizedString(#"Yes",nil), nil];
[alert show];
[alert release];
}
And the method thats checks which button has been pressed:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0:
{
NSLog(#"Delete was cancelled by the user");
}
break;
case 1:
{
NSLog(#"Delete deleted by user");
}
}
}
So, my question is, how can i send the aRecording parameter from the first method to the second?
Thanks a lot
Store that variable in a member variable (easiest solution)
If you are only passing an int variable, you can set AlertView tag
property.
myAlertView.tag = YOUR_INT;
According to the documentation,
Note : The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is
private
and must not be modified.
So please use the 3rd method only if you are not intending to submit
app to app store. Thanks user soemarko ridwan for the tip.
For passing complex objects, subclass UIAlertView, add an object
property
#interface CustomAlertView : UIAlertView
#property (nonatomic, retain) id object;
#end
#implementation CustomAlertView
#synthesize object;
- (void)dealloc {
[object release];
[super dealloc];
}
#end
When you create AlertView
CustomAlertView *alert = [[CustomAlertView alloc]
initWithTitle: NSLocalizedString(#"Cancel recording",nil)
message: NSLocalizedString(#"Are you sure you want to cancel the recording?",nil)
delegate: self
cancelButtonTitle: NSLocalizedString(#"No",nil)
otherButtonTitles: NSLocalizedString(#"Yes",nil), nil];
[alert setObject:YOUR_OBJECT];
[alert show];
[alert release];
In the delegate
- (void)alertView:(TDAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
NSLog(#"%#", [alertView object]);
}
the UIActionSheet crashes after it appears the second time through..
.H file
..UIActionSheetDelegate>{
UIActionSheet *popupQuery;
}
#property (nonatomic, retain) UIActionSheet *popupQuery;
.M file
-(IBAction)showActionSheet:(id)sender {
if (popupQuery.visible) {
NSLog(#"popupQuery isVisible");
[popupQuery dismissWithClickedButtonIndex:-1 animated:YES];
return;
}else{
popupQuery = [[UIActionSheet alloc] initWithTitle:#"Title" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Readibility" otherButtonTitles:#"Email URL", #"Print", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
//[popupQuery showInView:self.view];
[popupQuery showFromBarButtonItem:actionButton animated:YES];
[popupQuery release];
}
}
When you release popupQuery after showing it from actionButton, you relinquish ownership on the object. If the object gets deallocated then popupQuery will point to a deallocated object which when you do popupQuery.visible might give you a crash. Since you have it as a property, you can do this –
self.popupQuery = [[[UIActionSheet alloc] initWithTitle:#"Title" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Readibility" otherButtonTitles:#"Email URL", #"Print", nil] autorelease];
Remove the release statement at the end. Now the object will be valid when you popupQuery.visible or self.poupQuery.visible In this case, you will have the ownership and you can safely access the object.
From the documentation for UIActionSheet:
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
Parameters
buttonIndex
The index of the button that was clicked. Button indices start at 0.
Therefore the problem may be your -1.