How to add dynamically-named selector to a UIButton? - ios

I would like to add targets to UIButtons by dynamically generating the selector names for the buttons as I iterate through a for loop. So far, I have an NSArray of 3 UIButtons:
NSArray *buttonArray = #[email, webPage, textMessage];
I would like now to do something like:
for(UIButton *button in buttonArray){
[button addTarget:self action:#selector(CUSTOM NAME HERE) forControlEvents:UIControlEventTouchUpInside];
}
It would be nice if I could dynamically form a custom name based on the name of the button (for example the name of the selector would be the button name + "ButtonProc", but I could also use an NSArray containing strings correlating to the selector names. How can I do something like this?

Use NSSelectorFromString().
for(UIButton *button in buttonArray){
[button addTarget:self action:NSSelectorFromString(CUSTOM NAME HERE) forControlEvents:UIControlEventTouchUpInside];
}
Don't forget to add : at the end of your selector string if your #IBAction is declared with the sender argument.

Related

Xcode: Send value through target action from for loop

I've got a list of values coming from a database, which each has it's own unique id. I want to be able to delete a row from the list using that id. My issue is, I'm trying to understand how to send a value through the button action to be used in the called function.
For ex:
NSString *sId = [_idArray objectAtIndex:i];
_fId = [sId intValue];
[deleteBtn addTarget:self action:#selector(deleteFeed:_fId) forControlEvents:UIControlEventTouchUpInside];
The _fId is the value I'm trying to understand how to send to the function deleteFeed. I know it must be something simple, but I just can't pin it down when searching Google.
addTarget has defined set of params and you cannot send custom.
As a workaround you can do below:
Use the following api and set the _fId as TAG to the button:
action:#selector(deleteFeed:)
i.e.
[deleteBtn setTag:_fId]
[deleteBtn addTarget:self action:#selector(deleteFeed:) forControlEvents:UIControlEventTouchUpInside];
Now retrieve the tag from the button from the associated tag to identify the button.
- (void) deleteFeed:(UIButton*)sender{
[self deleteWithTag:sender.tag];
// Or place opening logic right here
}
I hope this helps.
What about subclassing UIButton? This way you'll be able to name the property something appropriate instead of reusing the ambiguous tag.
#interface ButtonWithData : UIButton
#property (assign) int aValue;
#end
- (void)yourForLoopFunction {
for (NSString *sId in _idArray) {
NSString *sId = [_idArray objectAtIndex:i];
ButtonWithData *deleteBtn = [ButtonWithData buttonWithType:UIButtonTypeCustom];
deleteBtn.aValue = [sId intValue];
[deleteBtn addTarget:self action:#selector(deleteFeed:) forControlEvents:UIControlEventTouchUpInside];
[someView addSubview:deleteBtn];
}
}
This will only work if you create a new button for each array item that you want to delete. Without more code context, I can't create a better example for you to follow, unfortunately.

how to pass data when button is clicked

Lets say I have 10 buttons. For each button i want to pass some text... e.g. Button 1, My New Button 2, etc....
What I want to do is print this text in NSLog.
Hence I created one method and passed this to button. But I am not getting how can I pass data into it...
[myButton addTarget:self action:#selector(btnSelected:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)btnSelected:(id)sender {
NSLog(#"btnSelected data is %#", sender);
// I want to print some text for respective button here...
}
But I am not getting... any idea how to get this done?
You can associate data with objects as :
Firstly import this class : #import <objc/runtime.h>
Then create a key as
static char * kIndexPathAssociationKeySTR = "associated_string_key";
then associate string as :
** Here you can associate any type of data with button like : NSMutableArray or NSString etcetra**
NSString *myAttachedValue = #"This is the info I am associating with button";
objc_setAssociatedObject(self.testBtn,
kIndexPathAssociationKeySTR,
myAttachedValue,
OBJC_ASSOCIATION_RETAIN);
then access it in your method you called on button event as :
- (IBAction)btnTouched:(UIButton *)sender {
NSString *valueIs = (NSString *)objc_getAssociatedObject(self.testBtn, kIndexPathAssociationKeySTR);
NSLog(#"value is : %#",valueIs);
}
Hope it helps you.
set tag for the button
[myButton addTarget:self action:#selector(btnSelected:) forControlEvents:UIControlEventTouchUpInside];
myButton.tag = 1;
now compare tag
-(IBAction)btnSelected:(id)sender {
UIButton *button = (UIButton *)
if(button.tag == 1) { //do button 1 stuff
NSLog(#"btnSelected data is %#", sender);
}
}
Also you can probably checkout Blocks, extend a uibutton to support blocks (UIButton block equivalent to addTarget:action:forControlEvents: method?).
Try this,
[myButton setAccessibilityValue:#"Some text"];
[myButton addTarget:self action:#selector(btnSelected:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)btnSelected:(id)sender {
NSLog(#"btnSelected data is %#", [sender accessibilityValue];);
// I want to print some text for respective button here...
}

Adding action to a UIButton in ios sdk

I am trying to add a button to a view programmatically and i am using the following code:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Click Me" forState:UIControlStateNormal];
[button addTarget:self action:#selector(click:) forControlEvents:UIControlEventTouchDown];
[button setFrame:CGRectMake(50, 20, 80, 70)];
[self addButton:button];
according to me code looks right but i am getting error "Unknown action click"
addbutton and click is the method of the same class
and i am adding the buttons in my constructor
what's the problem with the click method? is there any syntax error!
Your problem is that you have a method named click but your are telling your button that the method is named click:. Notice the difference (the colon).
Change the #selector to #seletor(click) so it matches the actual method name.
Another option is to leave the #selector as-is but update your click method to click::
- (void)click:(UIButton *)button {
// button was tapped - do something
}
A sample how to add a action to a button ....
UIButton *button = [UIButton buttonWithTypeRoundRect];
[button addTarget:self action:#selector(myMethod) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(10,10,100,50);
//Do some more Configuration of the button like title.. Look at UIButton Class Reference
[self.view addSubview:button];
SomeTimes you see a small colon(:) after the method name in the selector something like this #selector(myMethod:)
which means this method takes some argument. the colon plays no role in the name of the method. if you are not sending any argument to the function then don't put colon after the name of the function.....
In addtarget option you can see that self is specified because self contains myMethod function. Here you are supposed to specify the reference of that object which contains your Method.
change
- (void)click:(id)sender{ NSLog(#"Button Clicked"); }
or change action click: to click
[button addTarget:self action:#selector(click) forControlEvents:UIControlEventTouchUpInside];
hi just simply try this -(void)click { // do what ever } i.e just remove colon in #selector(click:) hope it will work

How do I add observer to UIButton?

I want be signaled when user will touch button (UIControlEventTouchUpInside). How do I add observer to UIButton?
Look at the documentation of UIControl.
[myButton addTarget:self
action:#selector(touch:)
forControlEvents:UIControlEventTouchUpInside];
This method works for anything that inherits from UIControl (including but not limited to UIButtons :)
// add target and action
[myButton addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
where the target is the class where the UIButton is added or implemented. If you set nil for addTarget, the action will go through the responder chain until a responder is found that responds to the buttonClicked: selector. buttonClicked: selector is implemented like the following:
-(void)buttonClicked:(id)sender
{
// do stuff here
}

How do I set and get UIButtons' tag?

How do I set a tag for a button programmatically?
I later want to compare to tags for a conclusion
I've tried this
-(IBAction)buttonPressed:(id)sender{
NSLog(#"%d", [sender tag]);
}
but that just crashes the app.
Any other ideas?
You need to cast sender as a UIButton:
-(IBAction)buttonPressed:(id)sender{
UIButton *button = (UIButton *)sender;
NSLog(#"%d", [button tag]);
}
Edit: Regarding the message "unrecognized selector"...
Based on your error message, it's not able to call the buttonPressed method in the first place. Notice in the error message it is looking for "buttonPressed" (no colon at end) but the method is named "buttonPressed:". If you are setting the button target in code, make sure the selector is set to buttonPressed: instead of just buttonPressed. If you are setting the target in IB, the xib may be out of sync with the code.
Also, your original code "[sender tag]" should also work but to access button-specific properties, you'll still need to cast it to UIButton.
I know this is an old question and been answered many a time in other questions, but it came up in a google search as second from the top. So, here is the answer to why it was crashing. Change it to 'button.tag'
-(void)myMethod
{
UIButton *theButton = [UIButton buttonWithType:UIButtonTypeCustom];
[theButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchDown];
theButton.tag = i;//or whatever value you want. In my case it was in a forloop
}
-(void)buttonPressed:(id)sender
{
UIButton *button = (UIButton *)sender;
NSLog(#"%d", button.tag);
}
No need for casting. This should work:
-(IBAction)buttonPressed:(UIButton*)sender
{
NSLog(#"%d", [sender tag]);
}

Resources