How to fire uibarbuttonitem click event programmatically
Asked Answered
C

8

20

I have created a UIActionSheet

UIActionSheet * action = [[UIActionSheet alloc]initWithTitle:@""
                                                              delegate:self
                                                     cancelButtonTitle: @"cancel"
                                                destructiveButtonTitle: @"OK"
                                                     otherButtonTitles: nil];
          [action showInView:self.view];
          [action release];

On the event of the cancel button in the UIActionSheet I want to fire the event of a UIBarButtonItem, which is in my view.

My question is how can I fire the button event(without touching the button) in the UIActionSheet delegate method

Caritta answered 29/2, 2012 at 9:44 Comment(3)
which method you are calling when User tap UIBarButtonItem?Chiquia
I am in a messy situation. I have a UIButton over this UIBarButtonItem. On the click of UIButton, I load a UIActionSheet. And on the click of the cancel button in UIActionSheet, I need to fire the event of UIBarButtonItem.Caritta
Paul i could not understand that why you make UIBarButtonItem if your UIBarButtonItem is under the UIButton?Advocacy
H
18

Not knowing the current bar button item action you can invoke it this way:

[barButtonItem.target performSelector:barButtonItem.action]

This will however bring "unknown selector" compiler warning, but this may be worked around.

Hotze answered 29/2, 2012 at 9:50 Comment(5)
UIBarButtonItem may not respond to sendActionsForControlEventsCaritta
does anyone else get ARC warning here "may cause leak"?Overissue
To suppress the "may cause leak" warning, see this answer.Stipe
Nope, it is absolutely valid case. You are allowed to use performSelector: as well as barButtonItem.action, no private API usage here.Hotze
Swift version: _ = editButton.target?.perform(editButton.action)Kenyon
B
28

Another way to do that and avoiding warnings is as follows:

[[UIApplication sharedApplication] sendAction:barButtonItem.action
                                           to:barButtonItem.target
                                         from:nil
                                     forEvent:nil];
Bastardize answered 20/8, 2014 at 19:45 Comment(1)
Thanks for the from nil, because most actions has senderCordelia
H
18

Not knowing the current bar button item action you can invoke it this way:

[barButtonItem.target performSelector:barButtonItem.action]

This will however bring "unknown selector" compiler warning, but this may be worked around.

Hotze answered 29/2, 2012 at 9:50 Comment(5)
UIBarButtonItem may not respond to sendActionsForControlEventsCaritta
does anyone else get ARC warning here "may cause leak"?Overissue
To suppress the "may cause leak" warning, see this answer.Stipe
Nope, it is absolutely valid case. You are allowed to use performSelector: as well as barButtonItem.action, no private API usage here.Hotze
Swift version: _ = editButton.target?.perform(editButton.action)Kenyon
C
14

@ton1n8o 's solution worked for me. Here is the implementation in swift:

UIApplication.sharedApplication().sendAction(barButtonItem.action, to: barButtonItem.target, from: nil, forEvent: nil)
Carisa answered 13/11, 2015 at 1:49 Comment(0)
P
2

I've read the accepted answer and it is awfully DANGEROUS. you should never suppress such warnings in order to shortcut the path to your desired result!

the safest way to do so:

SEL selector=barButton.action;
id target=barButton.target;
  if(selector && target){
     IMP imp = [target methodForSelector:selector];
     void (*func)(id, SEL) = (void *)imp;
     func(target, selector);
  }

Please read the original post here: performSelector may cause a leak because its selector is unknown

Praenomen answered 20/6, 2015 at 5:12 Comment(0)
S
2

For my case with RxCocoa I needed to provide a nil - object to the perform action otherwise it would crash with EXC_BAD_ACCESS:

let button = sut.navigationItem.leftBarButtonItem!
_ = button.target?.perform(button.action, with: nil)
Schoolroom answered 29/3, 2019 at 11:7 Comment(0)
U
1

You can use this method to fire the tap event programmatically for a specific button:

[self performSelector:@selector(buttonClicked:) withObject:self.myButton afterDelay:0.0]; 
Uziel answered 10/12, 2013 at 18:30 Comment(0)
H
0

Well this is how I use actionSheet ..

actionSheet  = [[UIActionSheet alloc] initWithTitle:nil 
                                                             delegate:nil
                                                    cancelButtonTitle:nil
                                               destructiveButtonTitle:nil
                                                    otherButtonTitles:nil];

[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];

CGRect pickerFrame = CGRectMake(0, 40, 0, 0);

UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;

[actionSheet addSubview:pickerView];
[pickerView release];

UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@"Done"]];
closeButton.momentary = YES; 
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:@selector(dismissActionSheet) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
[closeButton release];

[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];

[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];

Once you are done with this just define a selector in your .m like..

-(void)dismissActionSheet{
    [actionSheet dismissWithClickedButtonIndex:0 animated:YES]; 
}

so inside dismiss action sheet you can re-write what is happening inside bar button item... hope this helps.

Henryhenryetta answered 29/2, 2012 at 9:57 Comment(0)
T
0

Implement the delegate method

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex

OR

- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if(buttonIndex == actionSheet.destructiveButtonIndex)
    {

    }
    else if(buttonIndex == (actionSheet.cancelButtonIndex))
    {
        // Call your event here
        // Fire the event of UIBarButtonItem.
    }

}

actionSheet:didDismissWithButtonIndex:

Sent to the delegate after an action sheet is dismissed from the screen.

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex Parameters

actionSheet The action sheet that was dismissed. buttonIndex The index of the button that was clicked. The button indices start at 0. If this is the cancel button index, the action sheet is canceling. If -1, the cancel button index is not set.

Discussion: This method is invoked after the animation ends and the view is hidden.

actionSheet:willDismissWithButtonIndex:

Sent to the delegate before an action sheet is dismissed.

- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex Parameters

actionSheet The action sheet that is about to be dismissed. buttonIndex The index of the button that was clicked. If this is the cancel button index, the action sheet is canceling. If -1, the cancel button index is not set.

Discussion This method is invoked before the animation begins and the view is hidden.

Tontine answered 29/2, 2012 at 10:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.