I made a simple app in which i am loading different .xib on each orientation,
I have two xib's Portxib and Landxib, in both xibs, i dragged a button and assigned a
tag value to it as 1 in both xib's.
and i wrote this code in my viewDidLoad
UIButton *btn=(UIButton *)[self.view viewWithTag:1];
[btn addTarget:self action:#selector(BtnClick:) forControlEvents:UIControlEventTouchUpInside];
here is the selector method,
-(void)BtnClick:(id)sender
{
NSLog(#"BtnClick");
}
Click event of UIButton is not getting fired...
OR
Is there any other way to call the same method of button from both the orientation ??
EDIT :
.h file
.m file
Make sure...
Button is placed in root view in xib as you are finding it in self.view OR make sure it is placed in correct view and use that view with viewWithTag
You have assigned tag 1, so just make sure no other control within
same view have tag 1 other wise button will not be recognized by tag. If this is going to be your case then just change tag of button to very unusual number for that view like 999 or any thing else and test.
EDIT
I am feeling like you view is not getting recognized at viewDidLoad where you have setup your code. So just comment out that code in viewDidLoad and shift in your changeOrientation method after loading nib.
-(void)changeOrientation
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if(orientation==UIInterfaceOrientationPortrait || orientation==UIInterfaceOrientationPortraitUpsideDown)
{
[[NSBundle mainBundle] loadNibNamed:#"PortraitXib" owner:self options:nil];
}
else
{
[[NSBundle mainBundle] loadNibNamed:#"LandscapeXib" owner:self options:nil];
}
//Adding this code here makes sense that nib is loaded and after that we are recognizing button from loaded view of nib.
UIButton *btn = (UIButton*)[self.view viewWithTag:1];
[btn addTarget:self action:#selector(BtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
Hope this helps.
In header file add
IBOutlet UIButton *btn;
reference this btn from your xib files.
Here in your case the btn you are using is not referenced from the xib files so the method is not firing
-(IBAction)BtnClick:(id)sender
{
NSLog(#"BtnClick");
}
make the function as IBAction and reference this from nib btn.
In this case you no need to addtarget explicitly.
If you are not adding the button in the nib, then dont forget to init and addsubview to the view
You can see this tutorial http://www.idev101.com/learn/interface_builder_connections.html
EDIT Check what is printing?
for (UIButton *but in [self.view subviews])
{
NSLog("but.tag %d",but.tag);
if(but.tag==1)// compare for same row elements
{
NSLog("Button Added");
[btn addTarget:self action:#selector(BtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
}
You can add a button like this.
Add this to you didLoad method
UIButton* aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTag:1];
[aButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[aView addSubview:aButton];
}
// then ...
- (void)buttonClicked:(UIButton*)button
{
NSLog(#"Button %d clicked.", [button tag]);
}
Related
I added 3 buttons programmatically to my view, then I added the buttons to an array so that I can access them at a later time:
for (i = 0; i < 3; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[view addSubview:button];
[_buttons addObject:button];
}
If I reference the button in my array and change the image of the button, it does not change the button on screen.
UIButton* button = [_buttons objectAtIndex: 0];
[button setImage:thumb forState:UIControlStateNormal];
I've found a way to change the image of the button by looping through all the subviews in my view, but is there a better way?
for (UIView* subView in ((UIView*)[self.view.subviews objectAtIndex:0]).subviews){
if ([subView isKindOfClass:[UIButton class]]){
UIButton *button = (UIButton*)subView;
if (button.tag == self.selected){
[button setImage:thumb forState:UIControlStateNormal];
}
}
}
A common reason for this is that your array has not been initialized. When this happens, Objective C does not complain or throw excetions: instead, it behaves as if the calls to add elements never happened. It also returns nil when you try getting items back.
Add this line to your viewDidLoad method:
_buttons = [NSMutableArray array];
This should solve the problem.
Possible this could help on a click event:
-(void)clickEvent:(id)sender
{
[sender setImage:thumb forState:UIControlStateNormal];
}
If this is how you are picking up the event.
When you do addSubview, view retains subview you are adding. Also addObject retains it. Hence both are different ojbects. Changing properties of object in array will not affect object retained by view.
You can avoid loop by using tags. While adding buttons on view set unique tags to them. And when you want to access them, get it using tag directly.
//set tags for buttons
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTag:999];
[view addSubview:button];
//access using tag
UIButton *button = (UIButton*)[view viewWithTag:999];
[button setImage:thumb forState:UIControlStateNormal];
Add a tag to the button after creating it. And later use that tag to get that button.
for (i = 0; i < 3; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = i+1;
[view addSubview:button];
[_buttons addObject:button];
}
Then you can access it like:
UIButton *button1 = (UIButton *)[self.view viewWithTag:1];
UIButton *button2 = (UIButton *)[self.view viewWithTag:2];
UIButton *button3 = (UIButton *)[self.view viewWithTag:3];
While adding UIControl programatically to use reference later add tag to it which should be different like:
yourBtn.tag = 111;
Now get reference of UIButton like this:
UIButton *button = (UIButton*)[yourViewWhereYouAdded viewWithTag:111];
I am adding a button in UIScrollView in StoryBoard
Below is the code i am using.
-(void)addScrollView
{
for(int i=0;i<[array count];i++)
{
UIScrollView *subScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 400, SUBSCROLLVIEW_WIDTH, SUBSCROLLVIEW_HEIGHT)];
UITextView *txtVwDetail = [[UITextView alloc] initWithFrame:CGRectMake(342, 0, TEXTVIEW_WIDTH, TEXTVIEW_HEIGHT)];
txtVwDetail.text = SAMPLE_STRING;
[self addSubScrollView:subScrollView];
[self.view addSubview:subScrollView];
[self.view addSubview:txtVwDetail];
}
}
-(void)addSubScrollView:(UIScrollView *)aSubScrollView
{
for(int i=0;i<[array count];i++)
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
aButton.frame = CGRectMake(intBtnX, (aSubScrollView.frame.size.height - 80)/2, 50, 80);
[aButton setImage:[UIImage imageNamed:[self.items objectAtIndex:i]] forState:UIControlStateNormal];
**[aButton addTarget:self action:#selector(btnSubImageClicked) forControlEvents:UIControlEventTouchUpInside];**
aSubScrollView.contentSize = CGSizeMake(intScrollViewWidth, aSubScrollView.frame.size.height);
[aSubScrollView addSubview:aButton];
}
}
In addSubScrollView method I have added Button and its click event which is getting crashed.
-(void)btnSubImageClicked
{
NSLog(#"btnSubImageClicked");
}
I am having scenario as
MyMainViewController is the sourceViewController for my created customSegue which is the UIStoryboardSegue class
MyMainViewController having a UIView as PlaceHolderView in which I am adding MydestinationViewContoller's View which is this Scrollview
-(void)perform
{
BrowseScreenVC *srcObj = (BrowseScreenVC *)[self sourceViewController];
UIViewController *dstObj = (UIViewController *)[self destinationViewController];
for(UIView *vw in srcObj.viewPlaceHolder.subviews)
{
[vw removeFromSuperview];
}
NSLog(#"dest : %#",dstObj.view);
NSLog(#"destobj :%#",dstObj);
srcObj.currentViewController = dstObj;
[srcObj.viewPlaceHolder addSubview:[dstObj.view retain]];
}
UPDATE
With answer I also have to change the line
srcObj.currentViewController = dstObj;
to
srcObj.addChildViewController = dstObj;
to make it working
you have to add target as follow:
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
#selector(), within these braces you have to provide the method that you want to perform. the ":" represents that the method has some argument. In this case the argument would be the button itself that is calling the method.
You have to implement your method then its signature would look like this
- (void)btnSubImageClicked:(id)sender{
// sender would be the button that is calling the method. you can use this object according to your requirements if you want.
// your code
}
if you want to call this method from somewhere else as well you can call it by passing sender argument nil. e.g [self btnSubImageClicked:nil];
Your action needs to accept an (id) sender argument, even if you are not using it:
-(void)btnSubImageClicked:(id) sender
{
NSLog(#"btnSubImageClicked");
}
In the addSubScrollView:
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
Button target should like
-(void) btnSubImageClicked:(id)sender{}
try this.
Updated:-
Please correct your code,change this line
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
Now working i checked.
Instead of
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
write this,
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
and for better practice always write this,
-(void) btnSubImageClicked:(id)sender{}
I'm trying to use dynamic buttons created via code (no IB) in my project and they appear where and how I want them but they don't fire their actions.
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.frame = CGRectMake(475, 302, 49, 58);
[button1 setTitle:#"1"
forState:(UIControlState)UIControlStateNormal];
[button1 addTarget:self
action:#selector(goToFirstTrailer)
forControlEvents:(UIControlEvents)UIControlEventTouchDown];
[myImageView addSubview:button1];
-(void)goToFirstTrailer {
[self startAnimator:#"OutsideToTrailer1_" forNumFrames:60];
}
The imageView this is placed on has buttons and User Interaction Enabled On.
Any light you can shed would be much appreciated.
I think you have the wrong signature of the action method change that line to
-(void) goToFirstTrailer:(id)sender {
and where you set the action to
[button1 addTarget:self action:#selector(goToFirstTrailer:) forControlEvents:....
Important is the colon after the message name because I changed the action method signature to include the sender.
Edit I wrote a small sample project with just an imageView in the MainWindow.xib and created a button programmatically as follows
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.frame = CGRectMake(0.f, 0.f, 50.f, 50.f);
[button1 setTitle:#"1"
forState:(UIControlState)UIControlStateNormal];
[button1 addTarget:self
action:#selector(goToFirstTrailer:)
forControlEvents:(UIControlEvents)UIControlEventTouchDown];
imageView.userInteractionEnabled = YES; // <--- this has to be set to YES
[imageView addSubview:button1];
[self.window makeKeyAndVisible];
return YES;
}
It is quick and dirty and yes, I am misusing the application delegate as the view controller. I know it is bad.
Here is the action method
- (void) goToFirstTrailer:(id)sender {
imageView.backgroundColor = [UIColor redColor];
}
Setting the userInteractionEnabled property on the parent imageView makes the difference. With it set to NO which is the default, no events are routed to the button.
If myImageView is a UIImageView object, adding a subview to it (like UIButton) only displays the image that object is represented by. If you add that UIButton as a subview of a UIView, it should work perfectly. Try adding an auxiliary UIView to your UIImageView and then add your button to a subview of the new auxiliary UIView, that should solve your problem.
This works fine for me. Note that I changed the event to UIControlEventTouchUpInside to allow the button press down state to be visible first.
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(20,400,88,35); //The position and size of the button (x,y,width,height)
[btn setTitle:#"Quit" forState:UIControlStateNormal];
[btn addTarget:self
action:#selector(showAbout)
forControlEvents:(UIControlEvents)UIControlEventTouchUpInside];
[self.view addSubview:btn];
I have taken customview in my code for UIButton.
UIButton *button= [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
[button addTarget:self action:#selector(checkedimage:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)checkedimage:(id)sender
{
NSLog(#"checkedimage");
if(checkImage == NO)
{
newImage = [UIImage imageNamed:#"a.png"];
checkImage=YES;
}
else if(checkImage==YES)
{
newImage = [UIImage imageNamed:#"b.png"];
checkImage=NO;
}
}
but when i click on UIButton it is not going to action checkedimage
why?
You have not set it up correctly and not really given us enough information to help you.
Have you anywhere in your code created an IBOutlet with the type of UIButton and name of button? If you have done that have you in IB assign that IBOutlet to the correct UIButton?
If you have done that as well you really should not declare a NEW UIButton in the code with the same name. It should already exist as a property in the current class you are working in.
If you have not done any of the above you need to ADD your newly created button to a view somewhere for it to be visible at all.
I advise you to read some basic tutorials on how to use IB.
There is nothing wrong with the code you posted.
Have you added this button to the view? Using interface builder?
I ran this test code based on what you sent, all works just fine:
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button= [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
[button addTarget:self action:#selector(checkedimage:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(100, 100, 120, 20);
[self.view addSubview:button];
}
-(IBAction)checkedimage:(id)sender {
NSLog(#"checkedimage");
}
I've set up a Button and add it to a view. I want to add a "done" button to the UIKeyboardTypeNumberPad. Here's my code.
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setImage:[UIImage imageNamed:#"DoneUp.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:#"DoneDown.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:#selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
// locate keyboard view
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
UIView* keyboard;
for(int i=0; i<[tempWindow.subviews count]; i++) {
keyboard = [tempWindow.subviews objectAtIndex:i];
// keyboard view found; add the custom button to it
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES)
[keyboard addSubview:doneButton];
}
Everything works great until I want to remove the button if I've got a Kayboard of type NumbersAndPunctuation for example.
If I click the button I use [(UIButton)*sender removeFromSuperview];
to prevent memory leaks.
But how do I remove the button from within an other function?
Thanks a lot!
Some other guys did ask that question somewhere else but didn't get a answer. I'am sure you can help :)
// Where self is a UIView subclass
NSLog(#"subviews: %#",self.subviews);
for(id view in self.subviews ){
if ([view isKindOfClass:[UIButton class]]) {
NSLog(#"Removing a button!");
[view removeFromSuperview];
}
}
You should store a reference to the button, instead of using a local variable. For example:
Header file:
#interface myObject : NSObject {
UIButton *doneButton;
...
Implementation file:
doneButton = [UIButton buttonWithType: UIButtonTypeCustom
...
To remove it (assuming you're in the same object:
[doneButton removeFromSuperview];
However, Apple may not take kindly to you adding buttons to their keyboard.
you can declare your button in your .h file, so you will be able to get access from all class methods