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
}
Related
In my code I want to open one view controller as presentviewcontroller using actionsheet. but when i click on the button of actionsheet view is not coming but it's code is executing.
Here is the code invoking the action sheet:
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#""
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Print Full Report",#"Print Only Selected Questions", nil];
//Creating Attributed String with System Font size of 30.0f
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:#"Print Options" attributes:#{NSFontAttributeName: [UIFont systemFontOfSize:20.0f] , NSForegroundColorAttributeName : [UIColor grayColor]}];
//Accessing the Alert View Controller property from Action Sheet
UIAlertController *alertController = [actionSheet valueForKey:#"_alertController"];
//Setting Attributed Title property of Alert View Controller
[alertController setValue:attrString forKey:#"_attributedTitle"];
[actionSheet showInView:self.view];
actionSheet.tag = 100;
And here are the delegate and associated methods:
- (void)actionSheet:(UIActionSheet *)popup clickedButtonAtIndex:(NSInteger)buttonIndex {
// tag 1 = save options. 2 = clear options
switch (buttonIndex) {
case 0:
[popup dismissWithClickedButtonIndex:0 animated:YES];
pdfFlag=1;
[self printReportAction];
break;
case 1:
[popup dismissWithClickedButtonIndex:1 animated:YES];
pdfFlag=2;
[self printReportAction];
break;
}
}
-(void)printReportAction{
[self presentViewController:previewer animated:YES completion:nil];
}
did you initialized controller to present?
if so, checked VC for present not nil
remove these calls:
[popup dismissWithClickedButtonIndex:0 animated:YES];
There could be several reasons why the code isn't working. However, ActionSheets were deprecated in iOS 8.3. I would suggest using UIAlertController instead. Using an UIAlertController allows you to use blocks which makes tracking how issues much easier and cleaner.
I have mocked up a sample project that recreates what you are trying to accomplish. https://github.com/andyast/ActionSheetTest
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");
}
}
I'm hoping someone can help me figure this out...I'm a beginner Xcode / Objective-C programmer. I'm working on a app that is a continuation of last semester.
1: So I created a button and I need it to execute this custom function:
- (void)cancelTapped {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Notification" message:#"Do you want to delete everything and go back to product selection?" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes"];
[alert setTag:1];
[alert show];
}
How/where do I put this function? Is it in the button properties? Or would I write this in a custom class/controller and link it to it?
2: How do I get it to listen for the alert to return on: - alertView:didDismissWithButtonIndex:
3: From there, how would I would write the logic to hide the page and pop the view?
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (alertView.tag == 1 && buttonIndex == 1) {
// Delete data and return to lobby
[self.navigationController popViewControllerAnimated:YES];
}
}
You will need a custom UIViewController to house the logic for your button and alert view interactions. I am assuming you know how to do that.
Once done, assuming you have a reference to your button property in your view controller, you can programatically add a target to your button and pass the selector cancelTapped as a parameter:
[myButton addTarget:self action:#selector(cancelTapped) forControlEvents:UIControlEventTouchUpInside];
Alternatively you could control-drag from the button in your Storyboard to the header file of your custom UIViewController, and define an IBAction. That will create an empty cancelTapped method in your implementation which you could then add your logic in.
As for listening on UIAlertView messages, you will need to make your custom UIViewController a delegate of the UIAlertView by passing "self" as the delegate in the following statement:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Notification" message:#"My Message" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes"];
Your CustomViewController should also be declared as a UIAlertViewDelegate.
CustomViewController.h
#interface CustomViewController : UIViewController<UIAlertViewDelegate>
#end
Hope this helps!
By the using VIewWillDisappear method to detect the press of The back button of NavigationItem:
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
// Navigation button was pressed. Do some stuff
[self cancelTapped];
}
[super viewWillDisappear:animated];
}
- (void)cancelTapped {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Notification" message:#"Do you want to delete everything and go back to product selection?" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes"];
[alert setTag:1];
[alert show];
}
For More info && also Custom UIBArButtonItem Check Here
I've been researching this and it seems that the only way to do this is using UIActionSheet, the question is that my UIActionSheet only covers half of the screen, my code is:
MyViewController *myVC = [[myViewController alloc] init];
UIActionSheet *myActionSheet = [[UIActionSheet alloc] initWithTitle:#"\n\n"
delegate:self
cancelButtonTitle:#"cancel"
destructiveButtonTitle:#"done"
otherButtonTitles:nil];
[myActionSheet addSubview:myVC.view];
[myActionSheet showInView:currentView];
[myActionSheet release];
Also how do I then dismiss this UIActionSheet from my MyViewController? Is there any better solution than this? Here's a screenshot of what I mean by loading half of the screen:
screenshot
Here's a sample project to illustrate my issue.
UIActionSheet will increase or decrease it's height according to the number of UIButtons in it. What you can do is add another view above your view with your desired alpha. And remove it from subview and add in subview according to your requirement i.e. add subview when you are displaying actionsheet and remove when you are dismissing UIActionSheet. I hope this is relevant to your question and it will help you to solve your problem.
The problem is because of the frame size of your TestViewController and method for adding the UIView as a subView of the UIActionSheet.
Make the following changes, and it is dismissing properly !
Implement willPresentActionSheet and addSubView in that method
- (IBAction)pressed:(id)sender
{
UIActionSheet *myActionSheet = [[UIActionSheet alloc] initWithTitle:#"\n\n" delegate:self cancelButtonTitle:#"cancel" destructiveButtonTitle:#"done" otherButtonTitles:nil];
[myActionSheet showInView:self.view];
[myActionSheet release];
}
- (void) willPresentActionSheet:(UIActionSheet *)actionSheet{
TestViewController *myVC = [[TestViewController alloc] init];
[actionSheet addSubview:myVC.view];
}
And in the viewDidLoad of the TestViewController, set
- (void)viewDidLoad
{
self.view.frame = CGRectMake(0,0 , 320, 60);
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
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.