How to trigger UIButton action programmatically - ios

I have several buttons in one class and their actions are separate.
I created the instance of that class in another class, and I have the UIButton array in the 2nd class. I want to call each button's action programmatically. Is there any way to do this in iOS?

UIButton has a method to invoke the targets/selectors that are linked to a certain control event:
[button sendActionsForControlEvents:UIControlEventTouchUpInside];
2022 Swift syntax:
someButton.sendActions(for: .primaryActionTriggered)

For Swift 3.0/4.0/5.0:
button.sendActions(for: .touchUpInside)

You can simply call first class's action method as instance method from other classes by passing a UIbutton id
e.g.:
in first class "ClassA"
- (IBAction)classAbuttonAction1:(id)sender;
- (IBAction)classAbuttonAction2:(id)sender;
from another class
UIButton *bClassButton = [[UIButton alloc]init];
ClassA *instance = [[ClassA alloc]init];
[instance classAbuttonAction1:bClassButton];
[instance classAbuttonAction2:bClassButton];

Related

Access Method from another controller

I have a button action function in a controller named as "Remotecontroller". this is the method:
-(IBAction)startDiscover:(id)sender{.....}
I have another controller named as "iptvViewcontroller". I need to call the above method in this "iptvViewcontroller" when a button click. this is my button click function:
btnRefresh3 = [UIButton buttonWithType:UIButtonTypeCustom];
btnRefresh3.frame = CGRectMake(0, 0, 25, 20);
[btnRefresh3 addTarget:self action:#selector(startDiscover:)
[arrLeftBarItems addObject:barButtonItem3];
Please somebody help me to make it work.
By creating and using custom delegate , you can achieve that functionality.
An Objective-C delegate is an object that has been assigned to the delegate property another object.
See below links for details and How to create and use custom delegate.
1.How do I create delegates in Objective-C?
2.How to use custom delegates in Objective-C
In Remotecontroller.m, set NotificationCenter like this in your viewDidLoad :
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(startDiscover) name:#"discover" object:nil];
In Remotecontroller.m
-(void)startDiscover
{
/////Your Code
}
In iptvViewcontroller.m
[btnRefresh3 addTarget:self action:#selector(startDiscoverFromRemoteController);
-(void)startDiscoverFromRemoteController
{
[[NSNotificationCenter defaultCenter]postNotificationName:#"discover" object:nil];
}
To call one method to another class you have to write your method in Remotecontroller.h file
-(IBAction)startDiscover:(id)sender;
then your remotecontroller class import in iptvViewcontroller class in .h file like this
#import "Remotecontroller.h"
now to use that method you have to create and alloc init object of remotecontroller class in iptvViewcontroller class in iptvViewcontroller.h file viewdidload() method
Remotecontroller *remote;
in iptvViewcontroller.m file
remote = [Remotecontroller alloc]init];
now you can use your method throughout the class
[remote startDiscover:parameter];

Access custom UIView class delegate method from parent class

I have a class name AccountRecoveryViewController. Here in UITableView's "customcell" which is called AccountRecoveryExpandedCell in - (void)awakeFromNib method I simply add a customView called RIPasscodeView. And set all necessary parameter.
Like this:
- (void)awakeFromNib
{
RIPasscodeView *passcodeView = [[RIPasscodeView alloc] initWithFrame:CGRectMake (32, 144, 278, 35)];
passcodeView.innerSpaceValue = 20;
passcodeView.placeHolder = #"-";
passcodeView.borderColor = [UIColor colorWithRed:250.0f/255.0f green:110.0f/255.0f blue:40.0f/255.0f alpha:1.0f];
passcodeView.delegate = self;
[self addSubview:passcodeView];
}
In RIPasscodeView I set the UITextFields delegate methods (textFieldShouldReturn or shouldChangeCharactersInRange) and it's works fine.
But now I want to access those UITextFields delegate methods from my AccountRecoveryViewController. Because I have to change the position of my tableview (up a little bit) by tap gesture, but the UITextFields delegate methods which is not available in this AccountRecoveryViewController class.
How can I do that? If any one have any suggestion or query please knock me.
Thanks a lot in advance.
You have several options to do this.
Create your own Protocol, and handle on action from inside the RIPasscodeView to AccountRecoveryViewController.
Assign the UITextField delegate to your parent controller, by passing the parent controller reference.
Use KVO.
Use NSNotificationCentre to notify your parent controller.
Cheers.

UIButton target to be UIViewController not custom UIView

I have a UIViewController which creates a custom sub view. The sub view is a UIView object which has been subclassed a few times.
Within the subview class I create a custom init method:
-(id)init {
self = [super init];
if (self) {
// Init code
[self spm_correctGuessViewCustomInit];
}
return self;
}
And within this I create a button and a label. The question relates directly to the button and its target action.
What I would like is for the UIViewController to have the buttons action, not the subclasses UIView (which actually creates and holds the button).
[continueButton addTarget:self.superview action:#selector(correctGuessContinueButtonPressed) forControlEvents:UIControlEventTouchUpInside];
I pass in the target of self.superview, this appears to work correctly and the correct method is run. However, I am shown a warning in the subclass 'Undeclared selector 'correctGuessContinueButtonPressed''
So am I implementing this approach correctly? Please let me know if more information is required.
One solution would be to update your custom view's init method so it takes target and action parameters (much like the addTarget: method of the button). You could then pass these values to the button via the addTarget: call.
- (instancetype)initWithTarget:(id)target action:(SEL)action {
// your normal init code here
// use target and action to setup your button
}
Your view.superview approach will not bring you to the view controller, but to a view.
You can import the header of your implementing class to fix the warning, but I think your design should be improved. Views should work pretty much on their own and not depend on their superviews, or even worse the whole architecture of views and controllers.
I'd pass a delegate down the line that gets called when the user pressed the button, or set some blocks on the views that get called when buttons fire.
Avoid communication over several layers of abstraction.
Reference previous similar question: Calling a method in a UIViewController from a UIButton in a subview
I had to add an import to the View Controller that the method was on, within the custom UIView subclass.
With the controller property set I could set the button target as controller
Ensure that the method that was being called from the button was in the controller header file, so could be seen by the subview implementation file. Previously this was not so the subview was not to know this existed.

Find UIGestureRecognizer action (selector) name and target

I'm trying to find which action is triggered by a UIGestureRecognizer on which target. Unfortunately there is no property on a UIGestureRecognizer such as gesture.action or gesture.target. The gesture I'm analyzing is part of UIKit private implementation.
Partial Answer here
stackOverFlow Question 20066315
Here's a code snippet that will list all target/action pairs associated with a gesture recognizer:
Ivar targetsIvar = class_getInstanceVariable([UIGestureRecognizer class], "_targets");
id targetActionPairs = object_getIvar(gesture, targetsIvar);
Class targetActionPairClass = NSClassFromString(#"UIGestureRecognizerTarget");
Ivar targetIvar = class_getInstanceVariable(targetActionPairClass, "_target");
Ivar actionIvar = class_getInstanceVariable(targetActionPairClass, "_action");
for (id targetActionPair in targetActionPairs)
{
id target = object_getIvar(targetActionPair, targetIvar);
SEL action = (__bridge void *)object_getIvar(targetActionPair, actionIvar);
NSLog(#"target=%#; action=%#", target, NSStringFromSelector(action));
}
Note that you'll have to import <objc/runtime.h>, and that this uses private ivars and a class, so it could get you banned from the App Store.
I have a different solution to this which has worked for me. This is more of a design change... you cannot access the target from the captured gesture. So instead keep a reference to the object when the touch down happened and before the pan began.
#property (nonatomic, strong) UIButton *myTouchedButton; // reference to button
(void)init
{
...
[card.button addTarget:self action:#selector(cardTouchDownInside:) forControlEvents:UIControlEventTouchDown];
...
}
-(void)cardTouchDownInside:(id)sender
{
NSLog(#"touch down on object");
self.myTouchedButton = (UIButton*)sender;
}

Selector from button created in category calls released method

I have a category of a class that creates a button that initializes properly with the following options
[cancelButton addTarget:self action:#selector(cancelReconnect:) forControlEvents:UIControlEventTouchUpInside];
then in the same category.m file I have the method
-(void)cancelReconnect{ NSLog(#"here!"); }
When the button is pressed in the viewcontroller that imports the class which imports the category I get an EXC_BAD_ACCESS and it appears my method/class seems like it was released.
If I put the same cancelReconnect method in the viewcontroller where 'self' would be. It is the same result.
Is my addTarget correct? is my selector method being released? How to solve this?
note the toolBarItems array in my custom class' .h file is strong but I don't know if the button in the array is. Does the View Controller keep a strong pointer to the Class's category method
You are making a common mistake. Your actual method is named cancelReconnect but you tell the button that the selector is named cancelReconnect: (notice the colon).
Change your method to:
- (void)cancelReconnect:(UIButton *)button {
NSLog(#"here!");
}

Resources