application Crash when assign multiple argu fun to dynamic button - ios

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).

Related

Adding multiple UIButtons to an UIView with a selector action

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;

Create a function that is able to check the title of the button pressed

I have a loop for creating buttons dynamically.
for (int b = 0; b < _currentPlayerTeams.count; b++)
{
HNTeamObject *team = _currentPlayerTeams[b];
CGFloat buttonY = 168 + ((b + 1) * distanceBetweenButtons) - 23;
NSString *buttonTitle = [NSString stringWithFormat:#"%# %#",team.teamName, team.seriesName];
UIButton *button = [[UIButton alloc] init];
button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:#"images.png"] forState:UIControlStateNormal];
button.titleLabel.textColor = [UIColor blackColor];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.backgroundColor = [UIColor clearColor];
[button addTarget:self
action:#selector(chooseTeamOne:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle: buttonTitle forState:UIControlStateNormal];
button.titleLabel.text = (#"%#", buttonTitle);
button.frame = CGRectMake(labelAndButtonX, buttonY, 268.0, 46.0);
[self.view addSubview:button];
}
I need to make a function that can act as the selector that for each button that is created and look at the button's title. Since I am making the buttons in the loop they are local and do not appear in another function that I create. Any help would be appreciated. I apologize in advance because I am very new to coding and am not quite up to speed with what is going on. Thanks.
Each button will call the chooseTeamOne: function when it is pressed so I assume you want to get the buttons title in that method.
To do so, use the UIButton's title property:
NSLog(#"%#", button.currentTitle);
This will log the button's current title. What is important to note is that I am referencing "button" which is the instance of the UIButton which called the chooseTeamOne method. I am assuming chooseTeamOne takes a UIButton button as a parameter.
If your method takes an 'id' as a parameter you would need to cast the sent object to a UIButton like this:
- (IBAction)chooseTeamOne:(id)sender {
UIButton *button = (UIButton *)sender;
NSString *buttonTitle = button.currentTitle;
}
Do you need a separate selector to return the title? If not then..
I imagine that your chooseTeamOne function is something along the lines of:
-(IBAction)chooseTeamOne:(id)sender {
...do things...
}
in which case, just add
-(IBAction)chooseTeamOne:(id)sender {
UIButton *button = sender;
NSString *stringThatYouWant = button.titleLabel.text; //get the text on the button
...do things...
}

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)
{
}
}

How to make a custom UIButton with a unique image and selector for each from an array?

I have several UIButtons created from an NSMutableArray. I'm trying to customize each UIButton with a unique image.
On the following line I'm not sure of the syntax to use to set an image for each button from the image array respectively:
[btn setImage:[UIImage imageNamed:[myImages objectAtIndex:3]] forState:UIControlStateNormal];
here's the rest of my code:
NSMutableArray* buttonArray = [[NSMutableArray alloc] init];
for(int i = 0; i < 8; i++)
{
// Custom UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0.0f, 2.0f, 52.0f, 52.0f)];
[btn setTitle:[NSString stringWithFormat:#"Button %d", i+1] forState:UIControlStateNormal];
NSArray * myImages = [NSArray arrayWithObjects:#"category0.png", #"category-clothing1.png" , #"category2.png", #"category3.png", nil];
[btn setImage:[UIImage imageNamed:[myImages objectAtIndex:3]] forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[buttonArray addObject:btn];
}
I would also like a different selector to be called for each button.
Something like this? I just saw your post about needing different actions for each button but I would instead check the sender of the button and adjust the code accordingly inside your (buttonPressed:) method. You should also make sure you have the appropriate amount of images for your button array so a better method may be to only create the amount of buttons based on your image array count. (answer edited to reflect this). I also wanted to add you should get in the habit of also changing the highlighted state of the image when changing the normal state so when you press the image it doesn't go blank.
NSMutableArray* buttonArray = [NSMutableArray array];
NSArray * myImages = [NSArray arrayWithObjects:#"category0.png", #"category-clothing1.png" , #"category2.png", #"category3.png", nil];
for(int i = 0;i < [myImages count]; i++)
{
// Custom UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0.0f, 2.0f, 52.0f, 52.0f)];
[btn setTitle:[NSString stringWithFormat:#"Button %d", i] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:[myImages objectAtIndex:i]] forState:UIControlStateHighlighted];
[btn setImage:[UIImage imageNamed:[myImages objectAtIndex:i]] forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[buttonArray addObject:btn];
}
This code contains image and selectors from array.
(This code is not compiled-check, may contain some small issue, sorry for inconvenience)
NSMutableArray* buttonArray = [NSMutableArray array];
NSArray * myImages = [NSArray arrayWithObjects:#"category0.png", #"category-clothing1.png" , #"category2.png", #"category3.png", nil];
// You need to assign string name and that should be your method name.
NSMutableArray *selectors=[[NSMutableArray alloc]initWithArray:#"sel1",#"sel2",#"sel3",#"sel4", nil];
for(int i=0; i<[myImages count]; i++){
// Custom UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0.0f, 2.0f, 52.0f, 52.0f)];
[btn setTitle:[NSString stringWithFormat:#"Button %d", i] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:[myImages objectAtIndex:i]] forState:UIControlStateHighlighted];
[btn setImage:[UIImage imageNamed:[myImages objectAtIndex:i]] forState:UIControlStateNormal];
SEL selector = selectorFromString([selectors objectAtIndex:i]);
[btn addTarget:self action:#selector(selector) forControlEvents:UIControlEventTouchUpInside];
[buttonArray addObject:btn];
}

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.

Resources