Adding multiple UIButtons to an UIView with a selector action - ios

I've added some buttons to an UIView (via addSubview) programmatically. I’ve added to this button an #selector with a function. However, they appear in the view but when I do click, the last button works only.
Into my .h:
#property (nonatomic, strong) UIButton * myButton;
Into my .m
for(int i=0;i<5;i++){
myButton = [UIButton buttonWithType: UIButtonTypeRoundedRect];
myButton.frame = CGRectMake(55, 55*i, 30, 30);
myButton.tag = i;
myButton.backgroundColor = [UIColor redColor];
[myButton addTarget:self action:#selector(myaction:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:myButton];
}
-(void)myaction:(UIButton *)sender{
if(sender.tag == 0){
NSLog(#“uibutton clicked %ld", (long)sender.tag);
}
}
How do I add the action to all buttons? not for the last only...

This works fine:
- (void)viewDidLoad {
[super viewDidLoad];
for(int i=0;i<5;i++){
UIButton *myButton = [UIButton buttonWithType: UIButtonTypeRoundedRect];
myButton.frame = CGRectMake(55, 55*i, 30, 30);
myButton.tag = i;
myButton.backgroundColor = [UIColor redColor];
[myButton setTitle:[NSString stringWithFormat:#"%ld", (long)i] forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(myaction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:myButton];
}
}
-(void)myaction:(UIButton *)sender{
NSLog(#"uibutton clicked %ld", (long)sender.tag);
}
The code you posted in your question appears to be "this is what my code looks like" rather than your actual code. That can cause problems when people try to help.
In the future, post your actual code.

Let's make it more dynamic by calculating the height of the button and adding padding based on the number of buttons.
:
-(void)viewDidLoad {
[super viewDidLoad];
NSInteger height = self.frame.size.height - 5*20; // 5 is the button count
and 20 is the padding
NSInteger buttonHeight = height/5;
for(int i=0;i<5;i++){
UIButton *myButton = [UIButton buttonWithType: UIButtonTypeRoundedRect];
myButton.frame = CGRectMake(55, buttonHeight*i+padding*(i+1), 150,
buttonHeight);
myButton.tag = i;
myButton.backgroundColor = [UIColor redColor];
[myButton setTitle:[NSString stringWithFormat:#"%ld", (long)i]
forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(myaction:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:myButton];
}}
-(void)myaction:(UIButton *)sender{
NSLog(#"uibutton clicked %ld", (long)sender.tag);
}
You could make it more dynamic by calculating the height of the button like this:
NSInteger height = self.frame.size.height - 5*20;
NSInteger buttonHeight = height/5;

Related

How to make 3 clickable area on a button in Objective-C

I'm new in objective-C and I've create a project that use a button to change some elements from my view. I would like that depending on what part of the button I click, it displays different elements than previous.
For exemple when I click on the left area from button a red circle appears and when I click in the middle, it's the blue circle that appears and in the right area it's a green circle.
I tried searching on google and stackoverflow but I have trouble understanding how the selector used in this case. Could someone help me?
PS: Sorry for the mistakes, my English is not very good
I help you.
First you need the create the small custom view programmatically or through the xib or storyboard
UIView *viewButton = [[UIView alloc] initWithFrame: CGRectMake ( 100, 100, 300, 300)];
[self.view addSubView:viewButton];
Then Create the 3 buttons inside the viewButton
//First Button
UIButton *buttonLeftRed = [UIButton buttonWithType:UIButtonTypeCustom];
OR
UIButton *buttonLeftRed = [UIButton buttonWithType:UIButtonTypeSystem];
buttonLeftRed.frame = CGRectMake(0, 0, 100, 100);
buttonLeftRed.tag = 1;
[buttonLeftRed setTitle:#"Red" forState:UIControlStateNormal];
[buttonLeftRed addTarget:self
action:#selector(actionPressMeOne:) forControlEvents:UIControlEventTouchUpInside];
[viewButton addSubview:buttonLeftRed];
//Second Button
UIButton *buttonMiddleBlue = [UIButton buttonWithType:UIButtonTypeCustom];
OR
UIButton *buttonMiddleBlue = [UIButton buttonWithType:UIButtonTypeSystem];
buttonMiddleBlue.frame = CGRectMake(100, 0, 100, 100);
buttonMiddleBlue.tag = 2;
[buttonMiddleBlue setTitle:#"Blue" forState:UIControlStateNormal];
[buttonMiddleBlue addTarget:self
action:#selector(actionPressMeSecond:) forControlEvents:UIControlEventTouchUpInside];
[viewButton addSubview:buttonMiddleBlue];
//Third Button
UIButton *buttonRightGreen = [UIButton buttonWithType:UIButtonTypeCustom];
OR
UIButton *buttonRightGreen = [UIButton buttonWithType:UIButtonTypeSystem];
buttonRightGreen.frame = CGRectMake(200, 0, 100, 100);
buttonRightGreen.tag = 3;
[buttonRightGreen setTitle:#"Blue" forState:UIControlStateNormal];
[buttonRightGreen addTarget:self
action:#selector(actionPressMeThird:) forControlEvents:UIControlEventTouchUpInside];
[viewButton addSubview:buttonRightGreen];
If you want to change circle button, you have to import the Quartzcore Framework
#import <QuartzCore/QuartzCore.h>
#pragma mark - UIButton Action Methods
//First
- (void)actionPressMeOne:(UIButton *)sender
{
NSLog(#"Pressed Button Tag is - %#",sender.tag);
UIButton *button = sender;
//Then do whatever you want to do here
//half of the width
button.layer.cornerRadius = button.frame.size.width/2.0f;
button.layer.borderColor=[UIColor redColor].CGColor;
button.layer.borderWidth=2.0f;
button.clipsToBounds = YES;
[button setBackgroundColor:[UIColor redColor]];
}
//Second
- (void)actionPressMeSecond:(UIButton *)sender
{
NSLog(#"Pressed Button Tag is - %#",sender.tag);
UIButton *buttonTwo = sender;
//Then do whatever you want to do here
//half of the width
buttonTwo.layer.cornerRadius = button.frame.size.width/2.0f;
buttonTwo.layer.borderColor=[UIColor blueColor].CGColor;
buttonTwo.layer.borderWidth=2.0f;
buttonTwo.clipsToBounds = YES;
[buttonTwo setBackgroundColor:[UIColor blueColor]];
}
//Third
- (void)actionPressMeThird:(UIButton *)sender
{
NSLog(#"Pressed Button Tag is - %#",sender.tag);
UIButton *buttonThree = sender;
//Then do whatever you want to do here
//half of the width
buttonThree.layer.cornerRadius = button.frame.size.width/2.0f;
buttonThree.layer.borderColor=[UIColor greenColor].CGColor;
buttonThree.layer.borderWidth=2.0f;
buttonThree.clipsToBounds = YES;
[buttonThree setBackgroundColor:[UIColor greenColor]];
}
Thank You:-)

Fetching the tag values on selector

I am working with the iphone project. In that i added 3 buttons with same selector name(i.e action). Now i am fetch the data from the database using the query. But it is showing me the data to 3rd button only when i am pressing any butoon out of three .
btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(80, 30, 200, 50);
[btn.layer setBorderWidth:0];
btn.tag = 1;
[btn setTitle:#"1" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(detail:) forControlEvents:UIControlEventTouchUpInside];
btn.titleLabel.font = [UIFont fontWithName:#"Zapfino" size:14.0];
[scrollview addSubview:btn];
btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(80, 30, 200, 50);
[btn.layer setBorderWidth:0];
btn.tag = 2;
[btn setTitle:#"2" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(detail:) forControlEvents:UIControlEventTouchUpInside];
btn.titleLabel.font = [UIFont fontWithName:#"Zapfino" size:14.0];
[scrollview addSubview:btn];
btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(80, 30, 200, 50);
[btn.layer setBorderWidth:0];
btn.tag = 3;
[btn setTitle:#"3" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(detail:) forControlEvents:UIControlEventTouchUpInside];
btn.titleLabel.font = [UIFont fontWithName:#"Zapfino" size:14.0];
[scrollview addSubview:btn];
this is the action which i am using.
-(IBAction)detail:(id)sender
{
detailViewController *detailvc =[[detailViewController alloc]initWithNibName:#"detailViewController" bundle:Nil];
detailvc.btntxt = btn.tag;
NSLog(#"name of btn :%ld",(long)btn.tag);
[self.navigationController pushViewController:detailvc animated:YES];
}
In nslog also i am getting the tab of 3rd button only
please help me out regarding this issue...
You are assigning 1 tag to a button
btn.tag = 1;
add different tag to each button
--
Also in your detail: take the tag from the sender and not your instance variable
- (IBAction)detail:(UIButton *)sender {
detailViewController *detailvc =[[detailViewController alloc]initWithNibName:#"detailViewController" bundle:Nil];
detailvc.btntxt = sender.tag;
NSLog(#"name of btn :%ld",(long) sender.tag);
[self.navigationController pushViewController:detailvc animated:YES];
}
You set the tag number of all 3 buttons to the same value (1). You need to use different values if you want to be able to tell your buttons apart.
Use tag 1 for the first button, tag 2 for the second, and tag 3 for the third.
Use the sender variable to get the button that triggered the action:
-(IBAction)detail:(id)sender
{
UIButton *button = (UIButton *)sender;
NSInteger buttonTag = button.tag;
// etc
}
Also, give each button it's own tag
btn.tag = 2; // and 3
And don't use the btn variable in the action method. It will only ever contain the last set variable, which is the third button in this case.
just use ((UIButton)sender).tag instead of btn.tag
The main problem with your code is that you are using just single button object ( & initializing it three times & adding three different tags & adding it to subviews.), which looks like an ivar.
So even if you have added three different tags to a single object instance the recent most will be reflected & so you are getting just 3 as tag, all time.
btn = [UIButton buttonWithType:UIButtonTypeCustom];
....
btn.tag = 1;
.
.
btn = [UIButton buttonWithType:UIButtonTypeCustom];
...
btn.tag = 2;
.
.
btn = [UIButton buttonWithType:UIButtonTypeCustom];
...
btn.tag = 3
Instead you either don't use btn object in ur target method or you can have three different buttons for a good understanding.
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
btn1.frame = CGRectMake(80, 30, 200, 50);
....
btn1.tag = 1;
.
.
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
btn2.frame = CGRectMake(80, 80, 200, 50);
...
btn2.tag = 2;
.
.
UIButton* btn3 = [UIButton buttonWithType:UIButtonTypeCustom];
btn3.frame = CGRectMake(80, 130, 200, 50);
...
btn3.tag = 3
Rest you need to modify the code of the target method as
-(IBAction)detail:(UIButton *)sender
{
detailViewController *detailvc =[[detailViewController alloc]initWithNibName:#"detailViewController" bundle:Nil];
detailvc.btntxt = sender.tag;
NSLog(#"name of btn :%ld",(long)sender.tag);
[self.navigationController pushViewController:detailvc animated:YES];
}
I hope this will certainly help you.
-(IBAction)detail:(UIButton*)sender
{
if(sender.tag==1)
{
}
else if(sender.tag==2)
{
}
else if(sender.tag==3)
{
}
}

Creating buttons with an Array

I have 44 buttons that I am adding to a scrollview and I was trying to use a series of arrays to do so. I have arrays for the name strings of the filenames, for the Y sizes of the pics (all x's are the same) and a few others.
The code that I have in my viewDidLoad that runs the method is this:
for (int i = 0; i < 44; i++) {
[self makeLabelsAndButtons:i];
}
And the method makeLabelsAndButtons is here:
-(void)makeLabelsAndButtons:(NSInteger *)indexPath{
NSString *nameString = [nameArray objectAtIndex:indexPath];
NSString *picString = [picArray objectAtIndex:indexPath];
NSInteger picNumb = [[numbers objectAtIndex:indexPath] integerValue];
NSInteger picXnum = [[picXCoords objectAtIndex:indexPath] integerValue];
Button = [UIButton buttonWithType:UIButtonTypeCustom];
[Button addTarget:self action:#selector(presPressed:)
forControlEvents:UIControlEventTouchUpInside];
Button.frame = CGRectMake(160.0, 240.0, 220.0, picNumb);
Button.center = CGPointMake(picXnum, 200.0);
[Button setBackgroundImage:[UIImage imageNamed:picString] forState: UIControlStateNormal];
[ScrollView addSubview:Button];
[ScrollView insertSubview:Button atIndex:1];
NSLog(#"name: %#, pic:%#, picY:%i", nameString, picString, picNumb);
}
The buttons are not being added, but I get no errors. I'm really not sure what I'm doing wrong
Thanks for any help!
EDIT: This is how I'm initializing my scrollview
ScrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0,0,320,480)];
ScrollView.showsVerticalScrollIndicator=YES;
ScrollView.scrollEnabled=YES;
ScrollView.bounces = YES;
ScrollView.userInteractionEnabled=YES;
[self.view addSubview:ScrollView];
[self.view insertSubview:ScrollView atIndex:1];
ScrollView.contentSize = CGSizeMake(20000,480);
Via a system of NSLogs I've determined that the buttons aren't being added to the view and I don't know why.
Change Your code according to following..... it may work
[Button setBackgroundImage:[UIImage imageNamed:picString] forState: UIControlStateNormal];
Replace above with
NSString *path = [[NSBundle mainBundle] pathForResource:#"picString" ofType:#"png"];
[Button setBackgroundImage:[[UIImage alloc] initWithContentsOfFile:path] forState: UIControlStateNormal];
I assume that you have two properties Button and ScrollView declared on your controller.
Rename the property ScrollView to scrollView for readability.
#property (nonatomic, weak) IBOutlet UIScrollView *scrollView;
Delete the property Button because you don't need it.
Update your code:
Button *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(presPressed:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(160.0, 240.0, 220.0, picNumb);
button.center = CGPointMake(picXnum, 200.0);
[button setBackgroundImage:[UIImage imageNamed:picString] forState: UIControlStateNormal];
[self.scrollView addSubview:button];
You don't need to both add the subview and insert it.
It might be that you weren't allocating ScrollView and sending messages to nil objects will not give you an error. You need to confirm that self.scrollView is not nil, if it is, then check that it is wired up properly in your view.
It seems like your scrollView is horizontally scrollable.
You can try
-(void)addButtonsToScrollView
{
//X Offset for button seperation
CGFloat xOffset = 10.0f;
NSUInteger buttonCount = 0;
//In each iteration buttonFrame would be adjusted to next buttonFrame
//This would be used to find the contentSize of scrollView
CGRect buttonFrame = CGRectMake(xOffset, 240.0, 220.0, 40.0f);
while (buttonCount<44)
{
NSString *nameString = nameArray[buttonCount];
NSString *picString = picArray[buttonCount];
CGFloat picNumb = [numbers[buttonCount] floatValue];
CGFloat picXnum = [picXCoords[buttonCount] floatValue];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(presPressed:)
forControlEvents:UIControlEventTouchUpInside];
buttonFrame.origin.y = (scrollView.frame.size.height - picNumb)/2;
buttonFrame.size.height = picNumb;
button.frame = buttonFrame;
[button setBackgroundImage:[UIImage imageNamed:picString]
forState: UIControlStateNormal];
[button setTitle:nameString
forState:UIControlStateNormal];
[scrollView addSubview:button];
buttonFrame.origin.x += buttonFrame.size.width+xOffset;
buttonCount++;
}
CGSize contentSize = scrollView.frame.size;
contentSize.width = buttonFrame.origin.x;
scrollView.contentSize = contentSize;
}

Adding actions to a button programmatically on iOS

I am trying to add an action to buttons which I am creating programmatically:
[btn addTarget:self
action:#selector(indexAction)
forControlEvents:UIControlEventTouchUpInside];
This works fine. However, I now want to pass a variable (int k) to the indexAction method. I couldn't get this to work:
[btn addTarget:self
action:#selector([self indexAction:k])
forControlEvents:UIControlEventTouchUpInside];
I am sure I'm doing something wrong. This is the context of the above code:
-(void) initIndexButtons {
float buttonPadding = -8;
float buttonWidth = 23;
float buttonHeight = 80;
CGRect frame = CGRectMake(0,0,0,0);
for (int k=0;k<5;k++)
{
UIButton* btn = [[UIButton alloc] initWithFrame:frame];; btn.tag = k;
btn.frame = CGRectMake(0, k*(buttonPadding+buttonHeight), buttonWidth, buttonHeight);
UIImage *newImage = [UIImage imageNamed:#"index.png"];
[btn setBackgroundImage:newImage forState:UIControlStateNormal];
[btn addTarget:self
action:#selector(self indexAction:k)
forControlEvents:UIControlEventTouchUpInside];
}
}
-(void)indexAction:(int *)buttonTag
{
NSLog(#"buttonTag: %i", buttonTag);
}
EDIT:
I changed my code to:
// ...
[btn addTarget:self
action:#selector(indexAction:)
forControlEvents:UIControlEventTouchUpInside];
//[self indexAction:k];
[indexView addSubview:btn];
[indexView sendSubviewToBack:btn];
}
}
-(void)indexAction:(id)sender
{
NSInteger *tid = ((UIControl *) sender).tag;
NSLog(#"buttonTag: %i", tid);
}
But now I get the warning message that "Initialisation makes pointer from integer without a cast for the line NSInteger *tid = ((UIControl *) sender).tag;
EDIT:
This is the right line of code:
NSInteger tid = ((UIControl*)sender).tag;
Normally the method that a button calls takes one parameter:
(id)sender
Take a look at the question - how to pass a variable to a UIButton action
tag is an NSInteger not NSInteger*
change to
NSInteger tid = ((UIControl*)sender).tag;
The way to do it is to set:
-(void)indexAction:(id)sender
{
NSLog(#"Tag=%#"[(UIButton*)sender tag]);
}
and the call:
[btn addTarget:self
action:#selector(self indexAction:)
forControlEvents:UIControlEventTouchUpInside];
}
not really sure about my casting, haven't tested that, but I think it should work!
Best of luck.

application Crash when assign multiple argu fun to dynamic button

for (int i=0;i<[tableDataSource count];i++)
{
NSDictionary *dict = [tableDataSource objectAtIndex:i];
rowText = [dict objectForKey:#"title"];
UIButton *btn = [UIButton buttonWithType: UIButtonTypeRoundedRect];
[btn setTitle:rowText forState:UIControlStateNormal];
[btn addTarget:self action:#selector(myActionbtnText:) forControlEvents:UIControlEventTouchUpInside];
btn.frame = CGRectMake(60, 40+2*(40*i), 200, 40);
btn.alpha = 0.81;
[self.view addSubview:btn];
}
I got error at assign Action to dynamic button my action is given Below, how to pass object/parameter when button event occurs.
-(void) myAction:(NSString *)btnText;
{
NSLog(#"%# Button Clicked",btnText);
}
Try this :
for (int i=0;i<[tableDataSource count];i++)
{
UIButton *btn = [UIButton buttonWithType: UIButtonTypeRoundedRect];
[btn setTitle:rowText forState:UIControlStateNormal];
[btn addTarget:self action:#selector(myActionbtnText:) forControlEvents:UIControlEventTouchUpInside];
btn.tag = i;
btn.frame = CGRectMake(60, 40+2*(40*i), 200, 40);
btn.alpha = 0.81;
[self.view addSubview:btn];
}
-(void) myAction:(UIButton*)sender {
NSDictionnary *dict = [tableDataSource objectAtIndex:sender.tag];
NSString* rowText = (NSString*)[dict objectForKey:#"title"];
NSLog(#"%# Button Clicked",rowText);
}
There are several things wrong with your solution.
UIButton does not respond to addTarget:action:withObject:forControlEvents: but rather addTarget:action:forControlEvents. This is why your application is crashing.
The selector should be #selector(myAction:). The parameter should not be included.
I'm pretty sure that it wouldn't work anyway since by the time the button is pressed rowText will be out of scope and no longer available. Which is why you should go with #MathieuF solution (Just make sure to specify the selector correctly).

Resources