UIActionSheet crashes after appearing again on iPad - ipad

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.

Related

Is there a way to stagger when multiple Alert Views show up in the same View Controller?

So I have two different UIAlertViews in the same view controller and both alerts can be triggered at the same time. When both alerts are triggered, both alerts pop up at the same time, with the alerts being layered on top of each other. Is there a way to stagger the alerts so that when the first alert comes up, the second alert will not pop up until the user dismisses the first alert? For my code, this is the format I'm using
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"ERROR!"
message:#"Error message here!"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
try the following:
create two properties
#property (weak, nonatomic) UIAlertView *visibleAlertView;
#property (strong, nonatomic) UIAlertView *pendingAlertView;
every time when you want to present an alertview from your code make a check
UIAlertView *newAlertView = [[UIAlertView alloc] init...
if (self.visibleAlertView) {
self.pendingAlertView = newAlertView;
} else {
self.visibleAlertView = newAlertView;
[newAlertView show];
}
and finally:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (self.pendingAlertView) {
UIAlertView *newAlertView = self.pendingAlertView;
self.pendingAlertView = nil;
self.visibleAlertView = newAlertView;
[newAlertView show];
}
}
hope that helps :)
EDIT
you could even stack the pending alertviews:
#property (strong, nonatomic) NSMutableArray *pendingAlertViews;
...
self.pendingAlertViews = [NSMutableArray array];
before presenting an alertview:
UIAlertView *newAlertView = [[UIAlertView alloc] initWithTitle:#"Title" message:#"Message" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
if (self.visibleAlertView) {
[self.pendingAlertViews addObject:newAlertView];
} else {
self.visibleAlertView = newAlertView;
[newAlertView show];
}
and in dismiss:
if (self.pendingAlertViews.count > 0) {
UIAlertView *av = self.pendingAlertViews.firstObject;
[self.pendingAlertViews removeObjectAtIndex:0];
self.visibleAlertView = av;
[av show];
}
hope it helps :)
Why don't you make a class level variable that indicates an alertView is open. Then before you open one you check that variable and if it's set you don't pop up the second one. Instead you could have it set another variable that indicates the second box should pop up. Then in the - alertView:clickedButtonAtIndex: method you can pop up the second one if the second variable is set.
I think I am pretty late for this but still posting as It might be useful for someone looking for this.
I have created a AQAlertAction subclass for UIAlertAction. You can use it for staggering Alerts, the usage is same as you are using UIAlertAction. All you need to do is import AQMutiAlertFramework in your project or you can include class also (Please refer Sample project for that). Internally It uses binary semaphore for staggering the Alerts until user handle action associated with current alert displayed. Let me know if it works for you.

ActionSheet keeps appearing for every button

I have a method which throws up an actionSheet which is populated by an array.
The problem is that as soon as I place that method in the sender for 1 button, it fires off for every single button press.
I only want it to display for the one button (btnPortfolio).
Here is the code for my buttons:
- (IBAction)btnPortfolio:(id)sender {
[self populatePortfolioList];
}
- (IBAction)btnAdd:(id)sender {
}
- (IBAction)btnRefresh:(id)sender {
}
and here is my method:
-(void)populatePortfolioList{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Choose your option"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
for (NSString *title in portfolio_list) {
[actionSheet addButtonWithTitle:title];
}
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:#"Cancel"];
[actionSheet showInView:self.view];
}
since you are using IBActions, I assume that you have somehow created the methods by ctrl+dragging from the buttons into your code? is that the case? it might be possible that you accidentally connected more than one of your buttons with the method btnPortfolio which causes populatePortfolioList to be called any time the button is pressed

Method won't fire when called

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?

Send a parameter to an AlertView

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]);
}

Modal prompt class name in iOS?

So I'm completely drawing a blank on the name of the class that draws one of these modal prompts with multiple options. I've attached a screenshot. It's the prompt that's confirming whether or not the user wants to sign out.
That's a UIActionSheet, Read UIActionSheet Class Reference.
Example
In your header, you need to add the <UIActionSheetDelegate> protocol. Then in your #implementation this is how you would call this specific sheet:
UIActionSheet * sampleSheet = [[UIActionSheet alloc] initWithTitle:#"Are you sure you'd like to sign out from Path?" delegate:self
cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Sign Out" otherButtonTitles:nil];
[sampleSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
[sampleSheet showInView:self.view];
And this is how you would handle the sheet:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch ( buttonIndex )
{
case 0:
NSLog(#"User Chose Cancel");
break;
case 1:
NSLog(#"User Chose to Sign out.");
break;
}
}
You want UIActionSheet Class Reference
See UIActionSheet, I think that's the class you're looking for.
UIActionSheet *popupQuery;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
//give the user an option to choose an image from their library or take a new photo...
popupQuery = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Take Photo", #"Choose From Library", nil];
popupQuery.tag = 0;
}
else {
//give the user an option to choose an image from their library or take a new photo...
popupQuery = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Choose From Library", nil];
popupQuery.tag = 1;
}
popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[popupQuery showInView:[self.view window]];
[popupQuery release];

Resources