UIActionSheet block view controller dealloc - ios

When in my View controller I touch on a button launch this simple code
- (IBAction)tapOnButton:(UIButton *)sender
{
UIActionSheet *act = [[UIActionSheet alloc] initWithTitle:#"test" delegate:self cancelButtonTitle:#"aa" destructiveButtonTitle:#"bb" otherButtonTitles:#"cc", nil];
[act showFromRect:CGRectMake(50, 50, 100, 100) inView:self.view animated:YES];
}
-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
}
}
I get a Actionsheet on screen, tap on any button of the Actionsheet and this closes.
When I run dismiss my viewcontroller is not performed dealloc .
If you do not touch the button and do not open the actionsheet the dealloc works .
is a big enough problem. Someone 's going on?
i'm on ios 8.1.3

I am experiencing the same problem using the deprecated UIActionSheet in iOS 8 iPad. Using iPhone (iOS 7 and iOS 8) and iOS 7 iPad, the problem cannot be reproduced.
The only solution right now that I have tested to be working is to use UIAlertController to present action sheets in iOS 8. If you use UIAlertController, the View Controller gets deallocated correctly.

Most likely some references are retained to the view controller - hence it is not being deallocated.
Please try setting the delegate explicitly to nil in the delegate method like below:
- (IBAction)tapOnButton:(UIButton *)sender
{
UIActionSheet *act = [[UIActionSheet alloc] initWithTitle:#"test" delegate:self cancelButtonTitle:#"aa" destructiveButtonTitle:#"bb" otherButtonTitles:#"cc", nil];
[act showFromRect:CGRectMake(50, 50, 100, 100) inView:self.view animated:YES];
}
-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
}
actionSheet.delegate = nil
}

Related

SLComposeViewController - "Attempt to present" errors in iOS 8

Updating some code for iOS 8. I ran into this error on an iPad only app which worked flawlessly in iOS 7. I'm using a UIActionSheet to present options of share options, Facebook and Twitter are giving me heck.
SLComposeViewController *facebookShare = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
//I add an image if there is one
//I set some initial text
[self presentViewController:facebookShare animated:YES completion:nil];
Pretty straight forward stuff. But on iOS 8 I get the below
Warning: Attempt to present SLComposeViewController: 0x1a238760> on
PostDetailViewController: 0x180c5200> which is already presenting
(null)
I've seen this error below and I get what its all about. However its saying my PostDetailViewController is already presenting (null)?!? So basically its already busy with nothing?
I've attempted to present the SLComposeViewController from other VC's in the hearty but I keep getting the Attempt to present error. I've tried presenting from
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController , and self.navigationController to no avail. I've also tried pushing the SLComposeViewController from self.navigationController which actually works but gives undesired results as it pushes an empty background then stays there until SLComposeViewController is closed and the user presses back.
Any leads would be great! Thanks in advance.
EDIT 1:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0)[self shareWithTwitter];
if (buttonIndex == 1)[self shareWithFacebook];
if (buttonIndex == 2)[self shareWithiMessage];
if (buttonIndex == 3)[self shareWithEmail];
if (buttonIndex == 4)[self SaveImageToCameraRoll];
}
-(void)shareWithFacebook{
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
//add animal URL
SLComposeViewController *facebookShare = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[facebookShare addURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.somelink.com/detail.aspx?id=%#",theAnimal.AnimalID]]];
//add image if there is one
if (theAnimal.PhotoUrl) {
[facebookShare addImage:imageView1.image];
}
//set initial text
if ([theAnimal.Sex isEqualToString:#"Male"]) {
[facebookShare setInitialText:[NSString stringWithFormat:NSLocalizedString(#"pop_his_fb_share", nil),theAnimal.Name]];
}else [facebookShare setInitialText:[NSString stringWithFormat:NSLocalizedString(#"pop_her_fb_share", nil),theAnimal.Name]];
[self presentViewController:facebookShare animated:YES completion:nil];
} else {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:[NSString stringWithFormat:NSLocalizedString(#"alert", nil)] message:[NSString stringWithFormat:NSLocalizedString(#"details_no_fb_account", nil)] delegate:nil cancelButtonTitle:[NSString stringWithFormat:NSLocalizedString(#"dismiss", nil)] otherButtonTitles:nil, nil];
[alert show];
}
}
I found out that in iOS 8 ActionSheet is actually considered a ViewController (at least I didn't know if it was before), hence the error message. The ActionSheet is attempting to be dismissed when a button is clicked on the delegate method I was using:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
This delegate gets me the button index on click however the ActionSheet is still visible. When a click occurs the presenting ViewController attempts to dismiss the ActionSheet and I get my error.
I switched to:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
(Note: didDismiss) So my sharing methods are not called until the presenting ViewController has dismissed the ActionSheet, then it is free to present the share ViewController!
Hope this helps someone else. Cheers!
Just try following thing.
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self presentViewController:fbViewController animated:YES completion:nil];
}];

Issue in UIActionSheet on iPad. Can press any button when it's showing

I'm having troubles with my UIActionSheet on iPad view. I really have no idea why I can press any button available on the current view when it is active.
Example: BarButtonItem pressed. UIActionSheet appears like a popover, while it is showing you can press Back BarButtonItem.
Is there any way to avoid this? I've tried this on iPhone view and it's pretty fine.
Try like this.
First create a property
#property (weak, nonatomic) UIActionSheet *actionSheet;
#synthesize actionSheet = _actionSheet;
After that button action
- (IBAction)clickActionSheet:(UIBarButtonItem *)sender {
if (self.actionSheet) {
// do nothing
} else {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Action sheet demo" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Do something else" otherButtonTitles:DO_SOMETHING_ELSE, nil];
[actionSheet showFromBarButtonItem:sender animated:YES];
}
}
Implement this UIActionSheetDelegate
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex(NSInteger)buttonIndex
{
NSString *choice = [actionSheet buttonTitleAtIndex:buttonIndex];
if (buttonIndex == [actionSheet destructiveButtonIndex]) {
// destroy something
NSLog(#"Destroy");
} else if ([choice isEqualToString:DO_SOMETHING_ELSE]){
// do something else
NSLog(#"Do something else");
}
}

What is wrong with my code trying to react to Popup Button [duplicate]

This question already has an answer here:
UIAlertView not functioning correctly
(1 answer)
Closed 8 years ago.
I am trying to make a popup appear when the user clicks a button with a warning, and if they click cancel, it will be dismissed, but if they click continue, I want it to present the view controller. Here is my code, but it only dismisses the popup no matter which button I press:
- (IBAction)latest:(id)sender {
alert = [[UIAlertView alloc] initWithTitle:#"WARNING" message:#"Continuing will use internet and may cause app to slow down in large crowds" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"Continue", nil];
[alert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 2) {
UIViewController *NVC = [self.storyboard instantiateViewControllerWithIdentifier:#"Latest"];
[self presentViewController:NVC animated:YES completion:Nil];
}
}
Your problem is simple - you need to pass self as the alert view's delegate, not nil.
Also, in your delegate method, don't hard code button indexes. Do this instead:
if (buttonIndex == alertView.firstOtherButtonIndex) {
}
You only have 2 options to click. Indexes start at 0 not 1 so change if (buttonIndex == 2) to if (buttonIndex == 1)
Ok I figured it out. I had to set the delegate to self, it was set to "nil".

Show ActionSheet in Popover- what am i doing wrong?

Sams **Teach Yourself iPad Application development in 24 hour's says I can "display an action sheet in a "nonanimated" fashion, filling a full popover view when it first appears...To do this, you need to show the action sheet with the method
showFromRect:inView:animated
with the "rect" set to the dimensions of the popover, the view set to the popover view controller's view, and "animated" set to false. The display of the action sheet would need to take place when the popover view is first loaded such as in the viewDidLoad method of the popover view controller.
OK, easy.. here's my code in my popover's viewDidLoad method:
- (void)viewDidLoad {
self.contentSizeForViewInPopover=CGSizeMake(400.0,400.0);
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Available Actions" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Destroy" otherButtonTitles:#"Negotiate", #"Compromise", nil];
[actionSheet showFromRect:[self.view bounds] inView:self.view animated:NO];
[actionSheet release];
[super viewDidLoad];
}
But this fails every time at the inView:self.view parameter with the exception:
Invalid parameter not satisfying view != nil
Any ideas?
Note, if I put this exact same code in an IBAction method and trigger it from a button in the popover, it works without a hitch!
One solution is to call the UIActionSheet in viewWillAppear or viewDidAppear: For example:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self showActionSheet];
}
- (void)showActionSheet {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Available Actions" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Destroy" otherButtonTitles:#"Negotiate", #"Compromise", nil];
[actionSheet showFromRect:[self.view bounds] inView:self.view animated:NO];
[actionSheet release];
}
self.view hasn't been instantiated completely yet when this code is called.
I would suggest, as a hacky alternative, to put in a short (.1 seconds or something) NSTimer with your IBAction method as the callback.

iPad's UIActionSheet showing multiple times

I have a method called -showMoreTools: which is: - (IBAction) showMoreTools:(id)sender {
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:#"Close" otherButtonTitles:#"Add Bookmark", #"Add to Home Screen", #"Print", #"Share", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleDefault;
popupQuery.dismiss
[popupQuery showFromBarButtonItem:moreTools animated:YES];
[popupQuery release];
}
When an user taps a UIBarButtonItem it displays that UIActionSheet, but then, if the user wants to close the UIActionSheet without taping the Close button, (taping the UIBarButtonItem, then it displays the UIActionSheet over the first UIActionSheet.
It's possible to implement somehow taping another time the UIBarButtonItem to close the UIActionSheet?
Thank you so much – I'm a newbie in iOS Programming!
In order to dismiss it when you click on the button twice, you need to keep track of the currently displaying ActionSheet. We do this in our iPad app and it works great.
In your class that has the showMoreTools, in the header put:
#interface YourClassHere : NSObject <UIActionSheetDelegate> {
UIActionSheet* actionSheet_; // add this line
}
In the class file, change it to:
-(IBAction) showMoreTools:(id)sender {
// currently displaying actionsheet?
if (actionSheet_) {
[actionSheet_ dismissWithClickedButtonIndex:-1 animated:YES];
actionSheet_ = nil;
return;
}
actionSheet_ = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:#"Close" otherButtonTitles:#"Add Bookmark", #"Add to Home Screen", #"Print", #"Share", nil];
actionSheet_.actionSheetStyle = UIActionSheetStyleDefault;
[popupQuery showFromBarButtonItem:moreTools animated:YES];
[actionSheet_ release]; // yes, release it. we don't retain it and don't need to
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
// just set to nil
actionSheet_ = nil;
}
I found another solution to this. The problem is that when using showFromBarButtonItem, the toolbar view is automatically added to the popover's list of passthrough views. You can modify (and clear) the passthrough views when using a UIPopoverController directly, but not when it's presented as part of a UIActionSheet.
Anyway, by using showFromRect, there is no toolbar that the popover can automatically add to its passthrough views. So if you know the (approximate) rectangle where your button bar is, you can use something like:
CGRect buttonRect = CGRectIntersection(toolbar.frame, CGRectMake(0, 0, 60, self.frame.size.height));
[popupQuery showFromRect:buttonRect inView:self animated:YES];
In the above example, my button is on the left hand side of the toolbar.
try by setting the flag(YES/NO)
-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
use
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
My method is similar to christophercotton's.
In my showActionSheet I check if the actionsheet is visible rather than instantiated:
- (IBAction)showActionSheet:(id)sender
{
if ([self.fullActionSheet isVisible]) {
[self.fullActionSheet dismissWithClickedButtonIndex:-1 animated:NO];
_fullActionSheet = nil;
return;
}
//actionsheet code
}

Resources