I have created five buttons in a for loop dynamically. Now I want to associate an OnClick event with every button which do different actions. How I can do this and how can I detect which button is clicked?
for (NSUInteger i=0;i<5;i++)
{
UIButton *myButton1 = [[UIButton buttonWithType:UIButtonTypeCustom]
initWithFrame:CGRectMake(5, 57,15, 15)];
[myButton1 setTitle:#"Click Me!" forState:UIControlStateNormal];
[myButton1 addTarget:self action:#selector(buttonClicked1:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:myButton1];
}
You could asseble the selector name into a string and turn the string into a selector:
for (int i=0; i<5; i++)
{
NSString *actionName = [NSString stringWithFormat:#"buttonClicked%i", i];
SEL action = NSSelectorFromString(actionName);
// …
}
But as the buttons will probably do something similar, it would be better if they all called the same method, where you would simply tell the buttons apart by the tag:
for (int i=0; i<5; i++)
{
// …
[button setTag:i];
[button addTarget:self action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
}
- (void) buttonClicked: (id) button
{
const int tag = [button tag];
switch (tag) { /* … */ }
}
By the way, why do so many people insist on writing NSInteger when you can simply type int? Is there a difference? No that I know of.
Why are you creating 5 buttons in a for loop?
Is there any particular reason why you're not using Interface Builder?
Also, the code you posted will place each button at the same position. A button will be on top of the previous button, and so on.
Related
I have an array of UIButtons in the following code. Problem I'm having is that I need a unique method associated with each button. At the moment any button that's pressed all use the action:#selector(buttonPressed:)
I'm stuck on how to have a method hooked up to each button.
// Create buttons
NSMutableArray* buttonArray = [NSMutableArray array];
NSArray * myImages = [NSArray arrayWithObjects:#"category-cafe-unsel.png", #"category-food-unsel.png", #"category-clothing-unsel.png", #"category-health-unsel.png", #"category-tech-unsel_phone.png" , #"category-tech2-unsel.png", #"catefory-theatre-unsel.png", #"category-travel-unsel.png", nil];
// only create the amount of buttons based on the image array count
for(int i = 0;i < [myImages count]; i++)
{
// Custom UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0.0f, 20.0f, 52.0f, 52.0f)];
[btn setTitle:[NSString stringWithFormat:#"Button %d", i] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:[myImages objectAtIndex:i]] forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[buttonArray addObject:btn];
}
thanks for any help
:)
Best option is to use same method for all buttons.For that you should use tags. So each button has its own tag.
btn.tag = i;
Here tag number will be used for differentiating which button was called.
And then in the method you can get the tags, this can also be done with a switch-statement:
-(void)buttonPressed:(UIButton*)sender
{
if( sender.tag == 1 ){
} else {
}
}
Use following code:
-(void)buttonPressed:(UIButton*)sender
{
UIButton *btn = sender;
for(int i = 0;i < [myImages count]; i++)
{
if (i == [btn tag]) {
//Your code
break;
}
}
}
It's completly working fine. When you'll get Tag value, you can perform operations as per tag value.
Thanks,
Hemang.
[btn addTarget:self action:#selector(NSSelectorFromString([NSString stringWithFormat:#"button%d", i])) forControlEvents:UIControlEventTouchUpInside];
And the corresponding actions would be:
-(void)button1:(UIButton*)sender
-(void)button2:(UIButton*)sender
-(void)button3:(UIButton*)sender
-(void)button4:(UIButton*)sender
and so forth.
However, alternatively consider having one action method only and using tags to separate the buttons within the action method.
on one viewController of my app there is a long list of 20 or so buttons added programmatically, all which i want to call the same method, but to identify themselves through their button tag, but i ran into a problem that has set me back a few hours of research and attempts.The basic problem is i dont quite know how to access a programmatically created button in any other method than the method that they were initialized in.
My questions summerized:
1) if i were to create the button in the viewDidLoad method, how can I access it in a void method that i create?
2) How can i access those button tags in the created void method?
Here is the code that i have so far, but it is producing errors that ill explain below.
-(void)viewDidLoad{
float itemScrollerXdirection =0;
float itemScrollerYdirection =0;
float ySize =70.0;
float xSize = 70.0;
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(itemScrollerXdirection,itemScrollerYdirection,xSize,ySize);
[button addTarget:self action:#selector(itemSelected) forControlEvents:UIControlEventTouchUpInside];
button.tag =1;
[button setTitle:#"button1" forState:UIControlStateNormal];
[itemScroller addSubview:button];
}
//no errors in the above code
-(void)itemSelected{
if ([sender tag] == 1) { //Gets error "Use of undeclaired identifier 'sender'"
button.hidden = YES; //Gets error "Use of undeclaired identifier 'button1'"
}
}
We aren't working in the mystical relm of ruby, things need to be initialized and stored somewhere inorder for you to call them, try this:
#.h
#interface MyController : UIViewController{
NSMutableArray *buttons;
}
#.m
-(void)init // Or whatever you use for init
{
buttons = [[NSMutableArray alloc] init];
}
-(void)viewDidLoad{
//blah blah (what you already have)
[button addTarget:self action:#selector(itemSelected:) //Add ":"
forControlEvents:UIControlEventTouchUpInside];
button.tag =0;
[buttons addObject:button] //Add button to array of buttons
//blah blah (what you already have)
}
-(IBAction)itemSelected:(id)sender{
UIButton* button = [buttons objectAtIndex:sender.tag]
button.hidden = YES;
}
Note: I'm doing this from memory on, so it might not work perfectly.
#.h
#interface MyController : UIViewController{
UIButton *buttons;
}
#.m
-(void)viewDidLoad{
float itemScrollerXdirection =0;
float itemScrollerYdirection =0;
float ySize =70.0;
float xSize = 70.0;
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.button.frame = CGRectMake(itemScrollerXdirection,itemScrollerYdirection,xSize,ySize);
[self.button addTarget:self action:#selector(itemSelected) forControlEvents:UIControlEventTouchUpInside];
self.button.tag =1;
[self.button setTitle:#"button1" forState:UIControlStateNormal];
[itemScroller addSubview:button];
}
//no errors in the above code
-(void)itemSelected
{
if ([sender tag] == 1)
{
self.button.hidden = YES;
}
}
I am creating some UIbutton dynamically. And a user click any one of the buttons will display something (ex: different views). So I successfully made the buttons, get the tags. But in the IBAction method below, because all these buttons are dynamically created. So I can't use if, else if statement to show the view based on the tag number. I am thinking of using loops? any ideas?
Here is my code:
NSMutableArray *buttonsArray = [[NSMutableArray alloc] initWithObjects:nil];
for(int i = 0; i < [someArray count]; i++)
{
button = [[UIButton alloc] initWithFrame:CGRectMake(btnX,btnY,btnW,btnH)];
button.tag = i;
[buttonsArray addObject:button];
[[buttonsArray objectAtIndex:i] addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
button.titleLabel.text = [NSString stringWithFormat:#"Click it"];
[self.view addSubview:button];
btnY = btnY + 120;
}
`-(IBAction) buttonPressed:(id)sender `
{
UIButton *btn = (UIButton *)sender;
NSLog(#"%ld", btn.tag);
//Don't know the number of buttons, so this is not gonna work
if( btn.tag == 1)
{
//do something
}
if( btn.tag == 2)
{
//do something
}
if( btn.tag == 3)
{
//do something
}
if( btn.tag == 4)
{
//do something
}
}
loop is not the perfect solution here i think...agree with Jennis...use switch instead of if else statement...if you want to use loop try:
-(IBAction) buttonPressed:(id)sender{
UIButton *selectedbtn = (UIButton *)sender;
for (UIButton *bttn in buttonsArray) {
if ([bttn.tag == selectedbtn.tag ) {
//do something
}
}
}
you get Multiple UIbutton ? b'coz your X and Y are same for all..
All is OK in your code except two things.
(1) Change the coordinates of buttons so you get different position for all the buttons in the view.
(2) Change the following code:
[[buttonsArray objectAtIndex:i] addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
with this code:
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
Let me know if any further help required.
I have created a couple of buttons programatically in code (in a for-loop). If the user touches and drags one of these buttons, I would like to animate the button frame and then delete it (so a bit like the behaviour of the normal OS X Dock if you kick out an app).
My problem is that I don't know how to access the frame of a button: I only have the tag of the button as this is everything passed on to the delete method. How can I manipulate the frame if I only have the tag of a button?
Here is my code so far:
for (int k=0; k < numberOfTabs; k++) // k < 4 (e.g. 3 < 4)
{
UIButton* btn = [[[UIButton alloc] initWithFrame:frame] autorelease];
btn.tag = k;
btn.frame = CGRectMake(-10, 0, buttonWidth, buttonHeight);
[btn addTarget:self
action:#selector(tabAction:)
forControlEvents:UIControlEventTouchUpInside];
[btn addTarget:self
action:#selector(tabDelete:)
forControlEvents:UIControlEventTouchDragOutside];
...
And this is my tabDelete method so far:
-(void)tabDelete:(id)sender
{
NSInteger tid = ((UIControl*)sender).tag;
NSLog(#"buttonTag about to be deleted has the tag: %i", tid);
}
Cast the UIControl to a UIButton and you will have access to the frame, e.g.:
- (void)tabDelete:(id)sender
{
UIButton *button = (UIButton *)sender;
CGRect frame = button.frame;
}
-addTarget:action:forControlEvents: on UIButton always provides the UIButton instance as sender.
#albertamg: thank you, fixed :)
I want to programmatically add multiple UIButtons to a view - the number of buttons is unknown at compile time.
I can make one or more UIButton's like so (in a loop, but shorted for simplicity):
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Button x" forState:UIControlStateNormal];
button.frame = CGRectMake(100.0, 100.0, 120.0, 50.0);
[view addSubview:button];
Copied/Edited from this link:
How do I create a basic UIButton programmatically?
But how do I determine in buttonClicked: which button was clicked? I'd like to pass tag data if possible to identify the button.
You could either keep a reference to the actual button object somewhere that mattered (like an array) or set the button's tag to something useful (like an offset in some other data array). For example (using the tag, since this is generally must useful):
for( int i = 0; i < 5; i++ ) {
UIButton* aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTag:i];
[aButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[aView addSubview:aButton];
}
// then ...
- (void)buttonClicked:(UIButton*)button
{
NSLog(#"Button %ld clicked.", (long int)[button tag]);
}
You can assign a tag to the button.
button.tag = i;
Then in -buttonClicked:, check the tag of the sender:
-(void)buttonClicked:(UIButton*)sender {
int tag = sender.tag;
...
}
I think this would be the best answer:-
http://conecode.com/news/2012/05/ios-how-to-create-a-grid-of-uibuttons/
For that give different tag to each button & use code like this:
[btn1 addTarget:self action:#selector(pressbtn:) forControlEvents:UIControlEventTouchUpInside];
[btn2 addTarget:self action:#selector(pressbtn:) forControlEvents:UIControlEventTouchUpInside];
& in method
-(void)pressbtn:(id)sender {
UIButton *button=sender;
if (button.tag==1)
{
NSLog(#"Press button 1");
}
if (button.tag==2)
{
NSLog(#"Press button 2");
}
and so on to check which button is called
If you want to add buttons at run time then there will be 10 20 50 or more than that. Then you should to use ui scroll view in this condition.
When the buttons will be generate then your scroll view size should be increased accordingly.
And you can write the code like this
scrollview = [[UIScrollView alloc] init];
scrollview.contentSize = CGSizeMake(INVOICE_ADDITEM_SCROLLVIEW_CONTENT_WIDTH, INVOICE_ADDITEM_SCROLLVIEW_CONTENT_HEIGHT);
scrollview.frame = CGRectMake(0,50, SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGHT);
// scrollview.backgroundColor = [UIColor whiteColor];
scrollview.scrollsToTop = NO;
scrollview.delegate = self;
[self.view addSubview:scrollview];
for (int pos = 0; pos < 2; pos++) {
UIButton *but = [UIButton buttonWithType:UIButtonTypeCustom];
[but setImage:[UIImage imageNamed:#"checkbox.png"] forState:UIControlStateNormal];
[but setImage:[UIImage imageNamed:#"checkbox_active.png"] forState:UIControlStateSelected];
[but setFrame:CGRectMake(TXT_FLD_X_CORD+90, 295, 20, 20)];
// [but setCenter:CGPointMake( 50, i*40+20 )];
but.tag = pos;
/*if(pos==0)
{
[but setImage:[UIImage imageNamed:#"checkbox_active.png"] forState:UIControlStateNormal];
// [but setImage:[UIImage imageNamed:#"checkbox_active.png"] forState:UIControlStateSelected];
}*/
[but setCenter:CGPointMake(pos*90+125 ,310)];
[but addTarget:self action:#selector(checkboxButton:) forControlEvents:UIControlEventTouchUpInside];
[scrollview addSubview:but];
}
UIButton has a tag property. Use that and in your buttonClicked method, you can check the button that was clicked based on it's tag. Might want to keep constants around for what button is what.
For each of your buttons set an appropriate tag, and then refer to the tag in your action. i.e.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
...
button.tag = 1
[view addSubview:button];
You can easily set the tag based on the index of your iteration, if you're creating buttons in a loop. And then in your action:
- (void)aButtonWasTapped:(UIButton *)source {
if( source.tag == 1 ) {
// etc
}
}
Somebody might have this problem:
Jason Coco's answer worked fine for me, until I wanted to use the tag to access properties from an NSArray that was defined as a property.
Turns out the property had to be defined as "retain" instead of "weak".
The Swift version (with Labels):
for index in 1...5 {
var label = UILabel()
label.tag = index
labelsDictionary["Label\(index)"] = label
self.addSubview(label)
}
Call using using self.viewWithTag(i) as UILabel:
(cell.viewWithTag(5) as UILabel).text