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.
Related
I Follow the comment and try to fix my problem,but still not working.
when i run the test demo on the simulator,i get this:
run the demo project view
and i click the test2, i want to change button title before clear the button title, but i
get this :
after i click test2 button
i can not clear the button title when click another button.
anyone can help ??
Here is my code
-(void)addbutton
{
for (int i=0; i<3; i++)
{
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake((i*100), 0, 100, 100)];
button.titleLabel.text = #"";
[button setTag:i];
[button setTitle:[self.demoDataArray objectAtIndex:i] forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.backgroundColor = [UIColor clearColor];
[button addTarget:self action:#selector(setButtonTitle:) forControlEvents:UIControlEventTouchUpInside];
[self.demoView addSubview:button];
}
}
-(IBAction)setButtonTitle:(id)sender
{
if ([sender tag] == 0)
{
self.demoDataArray = [[NSArray alloc] initWithObjects:#"test5", #"test6", #"test7", #"test8", nil];
[self addbutton];
}
else if([sender tag] == 1)
{
self.demoDataArray = [[NSArray alloc] initWithObjects:#"test9", #"test10", #"test11", #"test12", nil];
[self addbutton];
}
else if([sender tag] == 3)
{
self.demoDataArray = [[NSArray alloc]initWithObjects:#"test13", #"test14", #"test15", #"test16", nil];
[self addbutton];
}
}
Every time any button is pressed, you instantiate new buttons and add them on top of the other ones. You probably want to just update the existing buttons. Try this for your -addButton method instead:
-(void)addbutton
{
for (int i=0;i<3;i++)
{
NSInteger tag = i+1;
UIButton *button = (UIButton *)[self.view viewWithTag:tag];
if (!button)
{
button = [[UIButton alloc] initWithFrame:CGRectMake((i*100), 0, 100, 100)];
[button addTarget:self action:#selector(setButtonTitle:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:tag];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.backgroundColor = [UIColor clearColor];
[self.demoView addSubview:button];
}
button.titleLabel.text = #""; // Not actually sure you need this...
NSString *titleText = nil;
if (i < self.demoDataArray.count)
titleText = [self.demoDataArray objectAtIndex:i];
[button setTitle:titleText forState:UIControlStateNormal];
}
}
Now the button is instantiated, given a target and action, tagged, and added into the button hierarchy only when it doesn't already exist. Every time a button is tapped after that, only the titles will be updated.
Also, very important:: in order for -viewWithTag: to work, you have to use a tag for your buttons that is not equal to 0, the default tag - otherwise the button's superview will be returned. This means you'll need to make the following changes in your button handler, which already had a bug with checking the tags (checking against 3 rather than 2). Increment the tags to start at 1 and end with 3 like so:
-(IBAction)setButtonTitle:(id)sender
{
if ([sender tag] == 1)
{
self.demoDataArray = [[NSArray alloc] initWithObjects:#"test5",#"test6",#"test7",#"test8", nil];
[self addbutton];
}
else if([sender tag] == 2)
{
self.demoDataArray = [[NSArray alloc] initWithObjects:#"test9",#"test10",#"test11",#"test12", nil];
[self addbutton];
}
else if([sender tag] == 3)
{
self.demoDataArray = [[NSArray alloc]initWithObjects:#"test13",#"test14",#"test15",#"test16", nil];
[self addbutton];
}
}
That method could use some cleanup as well to eliminate duplicated code and it's probably more appropriate to use a switch statement here anyways. But that's neither here nor there.
OK, this should probably get you up and running. I didn't test or compile this so if you do have some problem with the compiler that you're not able to work through on your own please let me know and I'll see if I can spot the issue.
try this
- (IBAction)firstbtn:(UIButton *)sender {
[secondbtn setTitle:#"" forState:UIControlStateNormal];
}
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 want to create uibuttons dynamically. so i for loop to create button with tag and added to view.
all buttons performs the same action with respect to its tag value... but i want to change the propery of the button. Therefore i need to get the uibutton using the tag value...
my code...
UIButton *button2;
//view did load
int width = 30;
for(int i = 1; i <= 5; i++)
{
button2 = [UIButton buttonWithType:UIButtonTypeCustom];
[button2 addTarget:self action:#selector(ratingAction:) forControlEvents:UIControlEventTouchUpInside];
[button2 setBackgroundImage:[UIImage imageNamed:#"star1.png"] forState:UIControlStateNormal];
button2.tag = i;
button2.backgroundColor = [UIColor clearColor];
button2.frame = CGRectMake(width, 78, 15, 15);
[self.view addSubview:button2];
width = width +30;
}
-(void)ratingAction:(id*)sender
{
// here using the tag value i want to get the button and change the background image….
// for example i want to change the background for tag values 1,3,6,7 ,8…
}
Use viewWithTag function of UIView to access your UIButton using the tag value.
See in Documentation viewWithTag
Use it as below.
UIButton* myButton = (UIButton*)[mySuperView viewWithTag:1];
UIButton* myButton = (UIButton*)[mySuperView viewWithTag:3];
UIButton* myButton = (UIButton*)[mySuperView viewWithTag:6];
.........
-(void)ratingAction:(id*)sender
{
// here using the tag value i want to get the button and change the background image….
// for example i want to change the background for tag values 1,3,6,7 ,8…
if ([sender isKindOfClass:[UIButton class]])
{
UIButton *temp=(UIButton*)sender;
if ([temp tag]==1 || [temp tag]==3 || [temp tag]==6 || [temp tag]==7 )
{
[temp setBackgroundColor:[UIColor redColor]];
}
}
}
Check this code
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
int y = 100;
for (int i=0; i<=5; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(80, y, 160, 40);
[button setTitle:[NSString stringWithFormat:#"Button-%i", i] forState:UIControlStateNormal];
// [button set
[self.view addSubview:button];
y=y+60;
}
}
-(void)aMethod:(id)sender{
UIButton *button = sender;
int y = 100;
int i = 5;
for (int x=0; x<=i; x++) {
NSString *frameString = [NSString stringWithFormat:#"{{80, %i}, {160, 40}}", y];
if ([NSStringFromCGRect(button.frame) isEqualToString:frameString]) {
NSLog(#"button %i clicked..", x);
}
y= y+60;
}
}
I am trying to create number of buttons on view programatically and for that I need array, so can I add button object in NSMutableArray?
Yes you can do that see the following code
// Create buttons for the sliding menu. For simplicity I create 5 standard buttons.
NSMutableArray *buttonArray = [[NSMutableArray alloc] init];
for(NSInteger i = 0; i < [self.slideMenuArray count]; i++)
{
// Rounded rect is nice
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
NSString *title=[slideMenuArray objectAtIndex:i];
[btn setFrame:CGRectMake(0.0f, 4.0f, 90.0f, 20.0f)];
[btn setTitle:[NSString stringWithString:title] forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor clearColor]];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[[btn titleLabel] setFont:[UIFont systemFontOfSize:12]];
[btn addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
UIImage *backgroundView;
if(i==0)
backgroundView= [UIImage imageNamed:#"btnclk.png"];
else
backgroundView= [UIImage imageNamed:#"btn.png"];
[btn setBackgroundImage:backgroundView forState:UIControlStateNormal];
[buttonArray addObject:btn];
}
You can retrieve the added button objects like this-
for(int i = 0; i < [buttonArray count]; i++)
{
UIButton *btn = [buttonArray objectAtIndex:i];
// Move the buttons position in the x-demension (horizontal).
CGRect btnRect = btn.frame;
btnRect.origin.x = totalButtonWidth;
[btn setFrame:btnRect];
}
sure you can, and remember that when you do, every button or other object will be retained bu the array and released when you remove it from the array...
Yes, NSMutableArray can hold any objects
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.