How to add an action to a UIButton - uibutton

I've been searching online for this answer, and every single post skips over the part of where to actually write the code for an action. I have a simple Interactive UIButton. And If i could just see a template of code that says "\write code for action here", that would be super helpful!!! ( it's for iPad IOS7 )
This is as far as I can get...
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(aMethod:)forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[view addSubview:button];
I think I understand that this is how to set up a potential action, but where do I write the actual code for the action itself?

I want to kind of expand more on what was answered here already, Both responses are correct but i want to explain why/how this all works.
[button addTarget:self
action:#selector(aMethod:)forControlEvents:UIControlEventTouchDown];
The first thing to look at; The target.
The target is the instance of a class, any class. The only requirement for this class is that it has to implement the action.
action is the method you wish to invoke when the user presses the button.
#selector(aMethod:) Basically think of this as a method signature. Because Objective-c is a dynamic language, aMethod: does not need to exist, but will crash your program if it does not.
So if we put this all together, Whenever I want to press this button:
The system will invoke the action method, on the target instance.
and for the method itself, it can look like this
- (void) aMethod:(id)sender { }

You would put the action related code in a method, in that class, named aMethod:
- (void)aMethod:(id)sender {
// your code for the action goes here
}
You perhaps might also want to use UIControlEventTouchUpInside for the control event.

Since you've set the target as self, the aMethod: method should be added to the same class.
- (IBAction)aMethod:(id)sender
{
// do something here
}

Related

UIButton added to subview in separate class where to store the method

In a program, I have a class called PullLeftMenu.h/.m.
In ViewController.m I am calling the PullLeftMenu like so:
PullLeftMenu *openMenu = [[PullLeftMenu alloc] init];
[openMenu classMethodHere];
So, simply runs a method with arguments. However, a part of this method of class PullLeftMenu is adding buttons to a subview that appears. Each button is assigned its own method to be called. Say for examples sake, button 1 calls method btnUsefulStuff.
I have put btnUsefulStuff method code in both the PullLeftMenu class and in the ViewController.m, and neither are being triggered - instead causing a memory crash.
Code for a button in PullLeftMenu.m
UIButton *btnUsefulStuff = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnUsefulStuff.frame = CGRectMake(10.0, 180.0, 160.0, 10.0);
[btnUsefulStuff setTitle:#"Useful Stuff" forState:UIControlStateNormal];
[btnUsefulStuff addTarget:self action:#selector(btnUsefulStuff) forControlEvents:UIControlEventTouchUpInside];
btnUsefulStuff.titleLabel.font = [UIFont fontWithName:#"KhmerUI" size:16];
btnUsefulStuff.titleLabel.textColor = [UIColor colorWithHexString:#"3a589b"];
[secondView addSubview:btnUsefulStuff];
And below this is the method:
-(void)btnUsefulStuff{
NSLog(#"button");
}
Problem is, I dont know where to place the method -(void)btnUsefulStuff as wherever I place it, it doesnt seem to get triggered and the app crashes with a memory warning. Error is:
Thread 1: EXC_BAD_ACCESS
Since this line [btnUsefulStuff addTarget:self action:#selector(btnUsefulStuff) forControlEvents:UIControlEventTouchUpInside]; is in PullLeftMenu and you're saying the target is self, that's where your method needs to be.
I suspect your problem is that you've made openMenu a local variable. Change it to a strong property inside ViewController so that it's still in memory when someone taps the button.

Easiest Way to Combine Two Statements for UIButton

I'm trying to condense my code, and I know there's an easier way than writing out two separate lines, but I can't seem to get the syntax just right. What I'm essentially doing is assigning an image to my UIButton, passing it to a method to automatically resize it, and then setting the title to NULL. Any ideas?
My code :
[self.btnA setBackgroundColor:[UIColor colorWithPatternImage:[self resizeImageWithImage:[UIImage
imageNamed:#"A_3rdStroke.png"] toSize:CGSizeMake(100, 100)]]];
[self.btnA setTitle:#"" forState:UIControlStateNormal];
maybe:
- (void)setButton:(UIButton *)button withImageName:(NSString *)imageName {
[button setBackgroundColor:[UIColor colorWithPatternImage:[self resizeImageWithImage:[UIImage imageNamed:imageName] toSize:CGSizeMake(100, 100)]]];
[button setTitle:#"" forState:UIControlStateNormal];
}
and you can call it from your class like this:
[self setButton:self.btnA withImageName:#"A_3rdStroke.png"];
optionally, you could put such method into a category for the UIButton class (which needs to include your -resizeImageWithImage:toSize: method as well).

How do I add a method to a button I made programmatically?

I'm working with a pre-existing xcode project for an iPhone app that retrieves flickr pictures. I want to add a favorite button so that a user can add a photo to an array of favorites, but I'm stumped because I've never made UI objects programmatically before.
Here is the code for my button, but how would I add a method do it? Also, where would this method definition go?
// Create favorites button
UIButton *favButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
favButton.frame = CGRectMake(200, 50, 100, 50);
[favButton setTitle:#"Favorite" forState:UIControlStateNormal];
favButton.backgroundColor = [UIColor clearColor];
[favButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal ];
UIImage *buttonImageNormal = [UIImage imageNamed:#"blueButton.png"];
UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[favButton setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
UIImage *buttonImagePressed = [UIImage imageNamed:#"whiteButton.png"];
UIImage *strechableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[favButton setBackgroundImage:strechableButtonImagePressed forState:UIControlStateHighlighted];
[favButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:favButton];
Is the addTarget method the way to add a method? Because whenever I click the button, it sends me back to xcode and shows me the main.m file and highlights this line of code:
int retVal = UIApplicationMain(argc, argv, nil, nil);
Sorry, I'm totally new to this. The project has the following files:
JSONFlickrAppDelegate.h
JSONFlickrAppDelege.m
JSONFlickrViewController.h
JSONFlickrViewController.m
ZoomedImageView.h
ZoomedImageView.m
Here is the xcode project that I am working off of:
http://compsci.cis.uncw.edu/~pattersone/courses/275/resources/JSONFlickrPart3.zip
Yes, this is the method that adds the method:
[favButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
The method, however, that will be called is playAction:. Whatever is located after addTarget is simply the object that will call the method, in the case of self, it is the object where this button is being created that it rests inside.
Looks like there are some confusions with how you need to add a target to a method.
Is the addTarget method the way to add a method?
Yes, you are correct. addTarget method is the way to add a method associated with the button and the method definition should be written on the class which is mentioned as addTarget param(In this case self, which is an object of current class).
When you use this line,
[favButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
It means that you are adding a method named playAction: to button which should be executed in target self on the event of UIControlEventTouchUpInside i.e, when an event occurs as user taps inside the button. So the action playAction should be inside the class which is represented by the object self i.e, the class in which you have written the above [favButton addTarget:... line. You can add any number of targets to this same button using similar addTarget lines.
but how would I add a method do it? Also, where would this method
definition go?
In this scenario, you need to define the method playAction: in the same class since you added target as self. This can be changed to any object of any class and the method can be written in that class.
for eg:-
- (void)playAction:(id)button {
//write the required code here, button is same as the favbutton which is written above.
}
Because whenever I click the button, it sends me back to xcode and shows me the main.m
file and highlights this line of code:
The reason why it is going back to xcode and shows the main.m is because it is a crashing since you haven't provided any playAction: method in your class. Since it cannot find any such method in the target self, it will crash and sometimes it just point to the main.m class.
You can also add target as follows,
[favButton addTarget:self action:#selector(playAction) forControlEvents:UIControlEventTouchUpInside];//notice that it is 'playAction' and not 'playAction:' with a colon at the end.
In this case your method will look like,
- (void)playAction {
//write the required code here
}
These are just different ways to do this.
For more details, please check this apple documentation.

target-action uicontrolevents

I must be missing something obvious here but ...
UIControl has a method
- (void)addTarget:(id)target action:(SEL)action forControlEvents: (UIControlEvents)controlEvents
which lets you add an action to be called when any of the given controlEvents occur. ControlEvents are a bitmask of events which tell you if a touch went down, or up inside, or was dragged etc., there's about 16 of them, you or them together and get called when any of them occur.
The selector can have one of the following signatures
- (void)action
- (void)action:(id)sender
- (void)action:(id)sender forEvent:(UIEvent *)
none of those tell you what the control event bitmask was. The UIEvent is something slightly different, it's related to the actual touch event and doesn't (I think) contain the UIControlEvent. The sender (UIControl) doesn't have a way to find the control events either.
I'd like to have one method which deals with a number of control events as I have some common code regardless of which event or events happened but I still need to know what the UIControlEvents were for some specific processing.
Am I missing a way to find out what UIControlEvents were used when the action was called or do I really have to separate my code into
- (void)actionWithUIControlEventX;
- (void)actionWithUIControlEventY;
I encountered the same problem, and came up with a solution. It's not amazingly pretty, but it works quite well. It is a UIControl category that stores the last UIControlEvent fired to its own tag property. You can get it from the link below. For further reference, here's the doc from my category, for a more detailed description of what's going on.
Hopefully this helps! Cheers/J
UIControl+CaptureUIControlEvents
git gist at: http://gist.github.com/513796
PROBLEM: upon firing, UIControlEvents are not passed into the target action
assigned to the particular event. This would be useful in order to have only
one action that switches based on the UIControlEvent fired.
SOLUTION: add a way to store the UIControlEvent triggered in the UIEvent.
PROBLEM: But we cannot override private APIs, so:
(WORSE) SOLUTION: have the UIControl store the UIControlEvent last fired.
The UIControl documentation states that:
When a user touches the control in a way that corresponds to one or more
specified events, UIControl sends itself sendActionsForControlEvents:.
This results in UIControl sending the action to UIApplication in a
sendAction:to:from:forEvent: message.
One would think that sendActionsForControlEvents: can be overridden (or
subclassed) to store the flag, but it is not so. It seems that
sendActionsForControlEvents: is mainly there for clients to trigger events
programatically.
Instead, I had to set up a scheme that registers an action for each control
event that one wants to track. I decided not to track all the events (or in
all UIControls) for performance and ease of use.
USAGE EXAMPLE:
On UIControl setup:
UIControlEvents capture = UIControlEventTouchDown;
capture |= UIControlEventTouchDown;
capture |= UIControlEventTouchUpInside;
capture |= UIControlEventTouchUpOutside;
[myControl captureEvents:capture];
[myControl addTarget:self action:#selector(touch:) forControlEvents:capture];
And the target action:
- (void) touch:(UIControl *)sender {
UIColor *color = [UIColor clearColor];
switch (sender.tag) {
case UIControlEventTouchDown: color = [UIColor redColor]; break;
case UIControlEventTouchUpInside: color = [UIColor blueColor]; break;
case UIControlEventTouchUpOutside: color = [UIColor redColor]; break;
}
sender.backgroundColor = color;
}
When you create your UIControl, set a value for the tag property. Then in your action function, you can determine the tag of the UIControl that called it using [sender tag]. Here's an example:
-(void)viewDidLoad {
UIButton *button1 = [[UIButton alloc] initWithFrame(CGRectMake(0.0,0.0,100.0,100.0)];
button1.tag = 42;
[button1 addTarget:self action:#selector(actionWithUIControlEvent:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button1];
UIButton *button2 = [[UIButton alloc] initWithFrame(CGRectMake(100.0,0.0,100.0,100.0)];
button2.tag = 43;
[button2 addTarget:self action:#selector(actionWithUIControlEvent:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button2];
}
-(void)actionWithUIControlEvent:(id)sender {
switch([sender tag]) {
case 42:
//Respond to button 1
break;
case 43:
//Respond to button 2
break;
default:
break;
}
}

selector keyword

-(void)clicketbutton{
UIButton *mybutton = [UIButton buttonWithType:UIButtonTypeCustom];
[mybutton setTitle:#"Click here" forState:UIControlStateNormal];
[mybutton addTarget:self action:#selector(displayvalue:)forControlEvents:UIControlEventTouchUpInside];
}
-(void)displayvalue:(id)sender{
UIButton *resultebutton= [UIButton buttonWithType:UIButtonTypeCustom];
resultebutton=sender;// pls clear here.. my question here , it it possible or not. if possible how ? NSLog(#" The buttontitile is %# ", [resultebutton.Title] // here also. }
In the above code I create a button and set title as Click here. When I press that button, I want to print Click here, I mean its title. For that my code is here.
iid is the sender, a pointer to the control that's calling your displayvalue method. You're casting the pointer to an integer, and printing the integer result. I'm not sure exactly what you're trying to accomplish, but the fastest way to get an integer from a button to the button's action method is to store it in the tag property.
If you go into a little more detail on what you're working on, I might be able to describe the best way to model that in a Cocoa app. Also, a tip-- be sure to fix any warnings in your code before trying to figure out why something's not working! That id -> int assignment would have made the compiler complain, for example.