UIButton and actions problem - iphone

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.

Related

How to have a method for each UIButton in an array

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.

How to see the tag of a programmatically created UIButton

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;
}
}

clear uibutton title and reset again

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];
}

manage multiple pressed UIButtons

I have a uiviewcontroller with many UIButtons that are meant to be selected and kept pressed until touched on again. I define each button in the viewDidLoad and give all of them the same selector method (tapButton):
[button1 addTarget:self action:#selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];
[button2 addTarget:self action:#selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];
...
What I would like to do, is in the tabButton: method, to use the selector to determine which button was pressed, and then change its state with the following:
- (IBAction) tapButton:(id)sender
{
if ( sender.selected ) {
sender.highlighted = NO;
sender.selected = NO;
} else {
sender.highlighted = YES;
sender.selected = YES;
}
}
You will notice that this is merely a pseuodo code since I can't really do "sender.selected" or "sender.highlighted" but thats what I am trying to accomplish.
is there any in way in which I can accomplish this? I would hate to create 30 "tapButton" methods (thats the number of UIButtons I have, yes...) for managing each UIButton's state.
Thanks a bunch!
You can set the tag of each button like this
button1.tag = 1;
button2.tag = 2;
....
Then in your selector
- (IBAction) tapButton:(id)sender
{
switch((UIButton*)sender.tag){
case 1:
.....
}
}
UIButton * selectedButton = [[UIButton allo]init];
/*for removing old highlight*/
selectedButton.higlighted = NO;
selectedButton = sender;
/*for setting new button highlight*/ sender.selected = YES
the above code will help you . Here am using new button to store last button state
You can use switch case for this...or you can also implement this by using alpha property...
-(IBAction) tapButton:(id)sender
{
UIButton *btn = (UIButton *)sender;
if ([btn isSelected])
{
btn.selected = NO;
btn.alpha = 0.5;
} else {
btn.selected = YES;
btn.alpha = 1;
}
}

UIButtons in UIScrollView stop it scrolling, how to fix?

I have a problem with adding a set of UIButtons to a UIScrollView. With the buttons added it seems that the scroll command is not being passed to the scroll view as the buttons cover the whole surface. I've read various posts on this but still can't figure it out. I'm pretty new to iPhone programming so there's probably something obvious I've missed. I've tried things like canCancelContentTouches and delaysContentTouches to TRUE and FALSE.
Here is the code I use to add the buttons to the UIScrollView. The UIScrollView was created in IB and is passed in to the function:
-(void)drawCharacters:(NSMutableArray *)chars:(UIScrollView *)target_view {
//NSLog(#"CLEARING PREVIOUS BUTTONS");
//clear previous buttons for parts/kanji
if(target_view == viewParts){
for (UIButton *btn in parts_buttons) {
[btn removeFromSuperview];
}
[parts_buttons removeAllObjects];
} else if(target_view == viewKanji){
for (UIButton *btn in kanji_buttons) {
[btn removeFromSuperview];
}
[kanji_buttons removeAllObjects];
}
//display options
int chars_per_line = 9; //change this to change the number of chars displayed on each line
if(target_view == viewKanji){
chars_per_line = 8;
}
int char_gap = 0; //change this to change the margin between chars
int char_dimensions = (320/chars_per_line)-(char_gap*2);
//set starting x, y coords
int x = 0, y = 0;
//increment y coord
y += char_gap;
//NSLog(#"ABOUT TO DRAW FIRST BUTTON");
for(NSMutableArray *char_arr in chars){
//increment x coord
x += char_gap;
//draw at x and y
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(x, y, char_dimensions, char_dimensions); // position in the parent view and set the size of the button
[myButton setTitle:[char_arr objectAtIndex:0] forState:UIControlStateNormal];
[myButton setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[myButton setTitleColor:[UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0] forState:UIControlStateDisabled];
myButton.titleLabel.font = [UIFont boldSystemFontOfSize:22];
if(target_view == viewKanji){
myButton.titleLabel.font = [UIFont boldSystemFontOfSize:30];
}
// add targets and actions
if(target_view == viewParts){
[myButton addTarget:self action:#selector(partSelected:) forControlEvents:UIControlEventTouchUpInside];
} else if(target_view == viewKanji){
[myButton addTarget:self action:#selector(kanjiSelected:) forControlEvents:UIControlEventTouchUpInside];
[myButton setTag:(int)[char_arr objectAtIndex:1]];
}
//if the part isnt in the current list of kanji, disable and dim it
if(target_view == viewParts){
if([kanji count] > 0){
[myButton setEnabled:NO];
}
bool do_break = NO;
for(NSMutableArray *arr in kanji){
//NSLog([NSString stringWithFormat:#"CHECKING PARTS AGAINST %d KANJI", [kanji count]]);
for(NSString *str in [[arr objectAtIndex:2] componentsSeparatedByString:#" "]){
if(([myButton.titleLabel.text isEqualToString:str])){
//NSLog(#"--------------MATCH!!!-----------------");
[myButton setEnabled:YES];
for(NSString *str1 in parts_selected){
if(([myButton.titleLabel.text isEqualToString:str1])){
[myButton setEnabled:NO];
break;
}
}
do_break = YES;
break;
}
if(do_break) break;
}
if(do_break) break;
}
}
// add to a view
[target_view addSubview:myButton];
//update coords of next button
x += char_dimensions+ char_gap;
if (x > (320-char_dimensions)) {
x = 0;
y += char_dimensions + (char_gap*2);
}
//add button to global array to be removed from view next update
if(target_view == viewParts){
[parts_buttons addObject:myButton];
} else if(target_view == viewKanji){
[kanji_buttons addObject:myButton];
}
}
//NSLog(#"FINISHED DRAWING ALL BUTTONS");
}
Any help on this would be greatly appreciated. I just need to fix this to finish my app.
You cannot expect the scrollview to receive events if the buttons cover the whole surface.(They are going to be first in the responder chain). The quick fix would be to make the buttons slightly smaller than the scrollview.
On first read of this problem I was thinking that you wanted to add buttons to the scrollview's superview -- but then I realized you actually want the buttons in the scrollview.