I have a button that doesn't call its target's selector.
When I click it, it does get highlighted. However, I set a break point at playButtonClicked and it never gets reached.
I'm not sure if it's being released, but I don't think so. I have ARC enabled and I can't call retain or release.
I've also tried explicitly enabling userInteractionEnabled but that doesn't make a difference either.
Here is my code:
#import "MainMenuView.h"
#implementation MainMenuView
- (void)initializeButton:(UIButton*)button withText:(NSString*)text buttonHeight: (int)buttonHeight buttonWidth:(int)buttonWidth buttonYInitialPosition:(int)buttonYInitialPosition buttonXPosition:(int)buttonXPosition
{
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(buttonXPosition, buttonYInitialPosition, buttonWidth, buttonHeight);
button.backgroundColor = [UIColor clearColor];
[button setBackgroundImage:[UIImage imageNamed:#"button.png"] forState:UIControlStateNormal];
[button setTitle:text forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont boldSystemFontOfSize:24];
[self addSubview:button];
[self bringSubviewToFront:button];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor yellowColor];
UIImage *backgroundImage = [UIImage imageNamed:#"title_background.jpeg"];
UIImageView *background = [[UIImageView alloc] initWithFrame:frame];
background.image = backgroundImage;
background.backgroundColor = [UIColor greenColor];
[self addSubview:background];
int centerWidth = frame.size.width / 2;
int centerHeight = frame.size.height / 9;
int centerXPos = frame.size.width / 4;
int buttonYInitialPosition = frame.size.height / 2 + frame.size.height / 20;
int buttonYOffset = frame.size.height / 7;
// init buttons
[self initializeButton:playButton withText:#"Play" buttonHeight:centerHeight buttonWidth: centerWidth
buttonYInitialPosition:buttonYInitialPosition buttonXPosition:centerXPos];
[playButton addTarget:self action:#selector(playButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void) playButtonClicked:(id)sender
{
NSLog(#"Play Button Clicked");
}
#end
Your code isn't doing what you think it is.
When you pass playButton in to -initializeButton:... and then immediately create a new button and assign it to that variable, you're no longer operating on the value that playButton points to. So when you call -addTarget:action:forControlState: afterwards, you're assigning a target to whatever playButton happens to point to, which is not the button you just created and added.
Passing a pointer is done (by default) by value, which means that you only have the address that the pointer held, not a reference to the pointer itself. So you can't change the pointer itself, only the object it points to. You can pass the pointer by reference, if you want to modify what it points to; or you can restructure your code so that you're always acting on the pointer directly—for instance, you could just use an ivar or property and have your initialize method set that property. Or you could return the button and assign it to your variable or property.
You are initializing the button incorrectly. A better approach is to have your initializeButton return the button.
- (UIButton *)initializeButtonWithText:(NSString*)text buttonHeight: (int)buttonHeight buttonWidth:(int)buttonWidth buttonYInitialPosition:(int)buttonYInitialPosition buttonXPosition:(int)buttonXPosition
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(buttonXPosition, buttonYInitialPosition, buttonWidth, buttonHeight);
button.backgroundColor = [UIColor clearColor];
[button setBackgroundImage:[UIImage imageNamed:#"button.png"] forState:UIControlStateNormal];
[button setTitle:text forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont boldSystemFontOfSize:24];
[self addSubview:button];
[self bringSubviewToFront:button];
return button;
}
Then call it this way:
playButton = [self initializeButtonWithText:#"Play" buttonHeight:centerHeight buttonWidth: centerWidth
buttonYInitialPosition:buttonYInitialPosition buttonXPosition:centerXPos];
I think you should do your initialization stuff in the method:
-(void)awakeFromNib {}
It's like the -viewDidLoad method for custom UIViews in that all the nib objects have been loaded and ready to go.
In the first line of your initializeButton method, you create a new Button. This new button is styled and added to the view hierarchy. This is the button that you see and that you can tap when you launch your app.
However, you apparently have another button named playButton. You pass it into the initializeButton method, but as written above, don't do anything with that reference. That means the addTarget: call goes to a button that you never add to your view hierarchy.
Related
I know how to set the enable = YES/NO, a button created using a property and xib. However, how do you do the same thing to a programmatically created button from another method in the same class?
For example here is my button in the viewDidLoad:
UIButton *AllList = [UIButton buttonWithType:UIButtonTypeCustom];
AllList.frame = CGRectMake(40, 80, 107.f, 53.5f); //set frame for button
UIImage *buttonImageFull = [UIImage imageNamed:#"allModsBtn.png"];
[AllList setBackgroundImage:buttonImageFull forState:UIControlStateNormal];
[self.view addSubview:AllList];
// add targets and actions
[AllList addTarget:self action:#selector(getButtons:) forControlEvents:UIControlEventTouchUpInside];
AllList.tag = 0;
I would like to set the enable of this button to YES or NO in another method.
#implementation {
UIButton *myButton;
}
- (void)viewDidLoad {
myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.tag = 121;
myButton.frame = CGRectMake(40, 80, 107.f, 53.5f); //set frame for button
UIImage *buttonImageFull = [UIImage imageNamed:#"allModsBtn.png"];
[myButton setBackgroundImage:buttonImageFull forState:UIControlStateNormal];
[self.view addSubview:myButton];
// add targets and actions
[myButton addTarget:self action:#selector(getButtons:)
forControlEvents:UIControlEventTouchUpInside];
myButton.tag = 0;
}
- (void)someOtherMethod {
myButton.enabled = YES;
OR
//In this case you dont need to define uibutton to globaly
UIButton *button = (UIButton*)[[self view] viewWithTag:121];
[button setEnabled:YES];
}
You have to make that button an ivar of your view controller.
#implementation {
UIButton *myButton;
}
- (void)viewDidLoad {
myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(40, 80, 107.f, 53.5f); //set frame for button
UIImage *buttonImageFull = [UIImage imageNamed:#"allModsBtn.png"];
[myButton setBackgroundImage:buttonImageFull forState:UIControlStateNormal];
[self.view addSubview:myButton];
// add targets and actions
[myButton addTarget:self action:#selector(getButtons:)
forControlEvents:UIControlEventTouchUpInside];
myButton.tag = 0;
}
- (void)someOtherMethod {
myButton.enabled = YES;
}
Something like this:
UIButton *myButton = [self.view viewWithTag:BUTTON_TAG]; // in your case is 0
[myButton setEnabled:YES];
Two ways to do it:
1) you can make it an ivar and then
AllList.enabled = YES;
or
[AllList setEnabled:YES];
2)
set a unique tag to the button
UIButton *AllList = [UIButton buttonWithType:UIButtonTypeCustom];
AllList.frame = CGRectMake(40, 80, 107.f, 53.5f); //set frame for button
AllList.tag = kUNIQUE_TAG;
in the method you want to mess with the button's enabled property
UIButton *theButton = (UIButton *)[self viewWithTag:kUNIQUE_TAG];
[theButton setEnabled:YES];
Everything about this UIButton renders great except the text that's supposed to be on it. NSLog demonstrates that the text is in the right place. What gives?
UIButton *newTagButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[newTagButton addTarget:self action:#selector(showNewTagField) forControlEvents:UIControlEventTouchUpInside];
newTagButton.titleLabel.text = #"+ New Tag";
NSLog(#"Just set button label to %#", newTagButton.titleLabel.text);
newTagButton.titleLabel.font = [UIFont systemFontOfSize:17];
newTagButton.titleLabel.textColor = [UIColor redColor];
CGSize addtextsize = [newTagButton.titleLabel.text sizeWithFont:[UIFont systemFontOfSize:17]];
CGSize buttonsize = { (addtextsize.width + 20), (addtextsize.height * 1.2) };
newTagButton.frame = CGRectMake(x, y, buttonsize.width, buttonsize.height);
[self.mainView addSubview:newTagButton];
There are a set of APIs on UIButton that should be used to change those properties.
The titleLabel can and will be changed by the UIButton internally.
[button setTitle:title forState:state];
[button setTitleColor:color forState:state];
[button setTitleShadowColor:color forState:state];
You should always set these properties through these methods (when available) rather than touching the titleLabel directly. For fonts you can change it on the titleLabel directly since they don't provide a method on UIButton.
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
I've created a UIButton on a view and on action of the UIButton[UIButton* button1_obj] one more button[UIButton* button2_obj] is created on same view.
i'm facing these 2 issues...please guide me how to proceed.
button1_obj is appearing when i run my project, but its not being clicked or highlighted, nor any exception is thrown.
On action of button1_obj , button2-obj has to appear on the same view, how to clear the view before placing button2_obj on it.
Code for question (1):
-(void)start
{
NSLog(#"--------------------------------------------------------------------");
NSLog(#"Entered CView start");
//define size and position of view
subMainView_G_obj = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 480, 320)]; //initilize the view
//subMainView_G_obj.autoresizesSubviews = YES; //allow it to tweak size of elements in view
UIButton_G_obj = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
UIButton_G_obj.frame = CGRectMake(100,70, 150, 50);
UIButton_G_obj.backgroundColor = [UIColor clearColor];
//UIButton_G_obj.adjustsImageWhenHighlighted = YES;
[UIButton_G_obj setTitle:#"UI" forState:UIControlStateNormal];
[UIButton_G_obj addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[subMainView_G_obj addSubview:UIButton_G_obj];
UIButton_G_obj = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
UIButton_G_obj.frame = CGRectMake(100,150, 150, 50);
UIButton_G_obj.backgroundColor = [UIColor clearColor];
UIButton_G_obj.adjustsImageWhenHighlighted = YES;
[UIButton_G_obj setTitle:#"Configuration" forState:UIControlStateNormal];
[UIButton_G_obj addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[subMainView_G_obj addSubview:UIButton_G_obj];
NSLog(#"Leaving CView start");
NSLog(#"--------------------------------------------------------------------");
}
- (void)action:(id) sender
{
NSLog(#"Inside action method.. On click of First View");
buttonUIObj = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
buttonUIObj.frame = CGRectMake(100,160,100,50);
[buttonUIObj setTitle:#"Next View" forState:UIControlStateNormal];
buttonUIObj.backgroundColor = [UIColor clearColor];
[subMainView_G_obj addSubview:buttonUIObj];
}
i've declare UIButton_G_obj,buttonUIObj,subMainView_G_obj GLOBALLY.
Hard to know what the problem with button1_obj is, without seeing code. However, for (2), you will probably want to remove button1_obj by calling [button1_obj removeFromSuperview].
About problem 1:
First of all both your buttons are named the same. Therefore you have a memory leak because your are allocating space for your button twice. Use different names for your buttons.
About problem 2:
You could hide button 2 until button 1 is pressed: In -(void)start
UIButton_G_obj_1.tag = 1;
...
UIButton_G_obj_2.hidden = YES;
UIButton_G_obj_2.tag = 2;
And in the action method you can unhide the button:
if (sender.tag == 1) {
UIButton_G_obj_2.hidden = NO;
}
I am trying to add a UIButton at runtime however it is not visible. What am I doing wrong?
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
btn.frame = CGRectMake(0, 0, 100, 25);
btn.backgroundColor = [UIColor clearColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick:)
forControlEvents:UIControlEventTouchUpInside];
btn.center = self.center;
[self addSubview:btn];
}
return self;
}
First, make sure the initWithFrame: method is being called. If your view is in a Nib, initWithCoder: is being called instead.
Second, is the button the only subview (from your code it looks like it is, but you never know). The button could be hidden behind another subview. Call bringSubviewToFront: if you need to.
Finally, is the view itself visible? Is it big enough to show the button? Given your example, if the view is less than 100 pixels wide, the button won't show because it will get clipped by the view's bounds.
You must release btn and remove ":" in buttonClick:
UIButton *btn= [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
btn.frame = CGRectMake(0, 0, 100, 25);
btn.backgroundColor = [UIColor clearColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
[btn release];
if it still doesn't work, try removing the : at the end of the selector name: #selector(buttonClick)
You don't need to retain the UIButton because it is retained by [self.view addSubview:btn];
First check whether your code is executing the initwithFrame method.
Because if you are loading the view from nib i.e using
NSArray *xibviews = [[NSBundle mainBundle] loadNibNamed: #"MySubview" owner: mySubview options: NULL];
MySubview *msView = [xibviews objectAtIndex: 0];
[self.view addSubview:msView];
Then the initWithFrame part will not be executing.So please check once.