The same button should do multiple task - iphone

I want one of my button to act different on different taps. Because its the same button i am using every time a particular action happens.
Is there a way to do this?
Thanks,

Add an additional UIGestureRecognizer ;)
Single tap is the action what will be linked but you can add other kind of gestures like double tap, swipe, etc.

You can use the tag property of button; so inside your IBAction method.
-(void)buttonClicked:(id)sender{
UIButton *button = (UIButton *)sender;
if (button.tag == 1) {
// perform your required functionality
button.tag = 2;
}
else if (button.tag == 2) {
// perform your required functionality
button.tag = 3;
}
else if (button.tag == 3) {
// perform your required functionality
button.tag = 1;
}
}
And don't forget to set initial tag value to 1.

If you want your button to act different you would create different methods to do the different actions. Then whenever you want the buttons behaviour to change you should set the button to handle the desired action.
So for the first action:
[button addTarget:self action:#selector(method1:) forControlEvents:UIControlEventTouchUpInside];
- (void) method1
{
//set button to handle method 2
[button addTarget:self action:#selector(method2:) forControlEvents:UIControlEventTouchUpInside];
}
- (void) method 2
{
}

The button just calls a method in your view controller when tapped. From there you do something like this:
if (internalState == FOO) {
[self doA];
} else {
[self doB];
}

Related

How to hide buttons which I had allocated in for loop?

I have created 3 UIbuttons on the top of the screen. Now after clicking every button I got the 5 buttons for each at below with different background images. Below is the code for my first button(located at top) by which I got 5 images in my view controller.
-(IBAction) btnforimages1click:(id)sender {
for (int a=0; a<5 ; a++) {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
buttonsforbundle1 = [[UIButton alloc]initWithFrame:CGRectMake(100*a,300 ,100 ,90 )];
[buttonsforbundle1 addTarget:self action:#selector(btn4images1:) forControlEvents:UIControlEventTouchUpInside];
buttonsforbundle1.tag = a;
[buttonsforbundle1 setBackgroundImage:[UIImage imageNamed:[bundle1 objectAtIndex:a]] forState:UIControlStateNormal];
[self.view addSubview:buttonsforbundle1];
}
}
I do the same for other two buttons also. Now here I want is, when I click any of my top 3 buttons
I just want to display the related buttons (created in for loop)
I want to hide the other buttons related to other Top most buttons.
Please suggest me how to solve this.
You have at least three options:
1) Access UI element by tag:
If you can manage to issue unique tag number in your btnforimages1click, btnforimages2click, btnforimages3click for your other 5 added UIButtons, then you can access them:
UIButton *button = (UIButton *)[self.view viewWithTag:99];
[button removeFromSuperview];
2) Keep reference of the created buttons:
// in view.h
NSMutableArray *my_created_buttons;
...
// in view init
[[my_created_buttons alloc] init];
...
-(IBAction) btnforimages1click:(id)sender {
for (UIButton *b in my_created_buttons {
[b removeFromSuperview];
}
if([my_created_buttons count]) {
[my_created_buttons removeAllObjects];
}
... let buttonsforbundle1 local variable since we store current 5 button set in array
UIButton *buttonsforbundle1;
... in your for loop add this after creating and adding to view
[my_created_buttons addObject:buttonsforbundle1];
}
You can further refactor these code eg. by making mutablearray management to other method.
3) Keep it in Interface Builder
I think it is the easiest option, create 5 UIButtons in Interface Builder and have 5 IBOutlet for them. Then in your btnforimages1click you can eg:
-(IBAction) btnforimages1click:(id)sender {
self.IBbutton1 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:0]] forState:UIControlStateNormal];
self.IBbutton2 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:1]] forState:UIControlStateNormal];
self.IBbutton3 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:2]] forState:UIControlStateNormal];
self.IBbutton4 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:3]] forState:UIControlStateNormal];
self.IBbutton5 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:4]] forState:UIControlStateNormal];
}
So you don't hide them, just change the background image. Moreover you don't have to deal with different touchUpInside event, use only one method, and in that one click method, you can distinguish between the different clicked UIButton by checking their tag (plus you have to use a variable to check which of the 3 top UIButton was clicked).

Button triggers two actions while pressing the changed button title

I have changed button title of a UIButton programmatically. I have also assigned an action to changed button title. Now when i tap on the button, it triggers both the action (one with same button title and one with changed). However, i want to trigger only one action for the changed title button.
How can i do it? Any help would be appreciated.
Two solutions. Toggle the target/action between methods or decide what to do based on some state.
1.
- (void)method1:(id)sender;
{
[sender removeTarget:nil action:NULL forControlEvents:UIControlEventTouchUpInside];
[sender addTarget:self action:#selector(method2:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)method2:(id)sender;
{
[sender removeTarget:nil action:NULL forControlEvents:UIControlEventTouchUpInside];
[sender addTarget:self action:#selector(method1:) forControlEvents:UIControlEventTouchUpInside];
}
2a.
- (void)buttonTapped;
{
if (self.someState) {
} else {
}
}
2b.
- (void)buttonTapped:(UIButton *)button;
{
if ([[button titleForState:UIControlStateNormal] isEqualToString:#"First title"]) {
} else {
}
}
if you assign two actions for the same button for control state touchupinside, it will always trigger both.You should remove the first action while adding the second and remove second itself and add the first again at the end of selector function.
The following is the default action of the button;
[button addTarget:self:action:#selector(actionOne)forControlEvents:UIControlStateTouchUpInside]
In the actionOne you can call remove observer for the first action and add the second one.
[button addTarget:self:action:#selector(actionTwo)forControlEvents:UIControlStateTouchUpInside]
And in actionTwo function you do the reverse
Instead of making two conditions
f([urlresponse status code] == 200)
{
[myButton setTitle:#"Unfollow" forState:UIControlStateNormal]; //title changed
[myButton addTarget:self action:#selector(unfollowButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
It might be helpful for your case.

Objective C Syntax: addTarget on UISwipeGestureRecognizer

I'm currently working on an app where the user has the option to either swipe through data, or use a button to go through the data. I'm having trouble understanding how to combine two bits of code.
Here is the code I'm using for swiping:
- (void)swipeRight:(UISwipeGestureRecognizer*)recognizer
{
if ([questions hasPrevQuestion] == YES) {
[self vorige:nil];
}
}
(the [self vorige:nil]; is calling the method for the button, so the swiping and the button have the same behavior)
and I need to somehow incorporate this code which applies to the button:
-(void)animationDidEndOnAnswer {
[vorigeButton addTarget:self action:#selector(newQuestion:) forControlEvents:UIControlEventTouchUpInside];
}
I think it's pretty simple, but I just cannot for the life of me figure out how to call the swiping method place of the button here...I'm thinking it's simple because I found this example in the UIGestureRecognizer class reference:
- (void)addTarget:(id)target action:(SEL)action
but being new to objective-c, I don't really know what to do with this. any help is very appreciated.
- (void)addTarget:(id)target action:(SEL)action is the code equivalent of binding a button action to a method like you do when you ctrl-drag from a button to an IBAction in Interface Builder.
So if your method is called vorige: and you want it to be called when the button is tapped, you would say:
[vorigeButton addTarget:self action:#selector(vorige:) forControlEvents:UIControlEventTouchUpInside];
But I don't know why you would want to do that as a result of an animation - you normally would set the button action once when the view is loaded, not change it during an animation.
Nick's solution is good.
if you want to call the same method for the swiping & the tap on your button, you can tweak your swipeRight like this:
- (void)goThrougtData:(id)sender
{
if( [sender isKindOfClass:[UISwipeGestureRecognizer class]] ) {
// swipe specific code
}
else if( [sender isKindOfClass:[UIButton class]] ) {
// tap specific code
}
if ([questions hasPrevQuestion] == YES) {
[self vorige:nil];
}
}
and in your init method, you add
[mySwipeRecognizer addTarget:self action:#selector(vorige:)];
[vorigeButton addTarget:self action:#selector(vorige:) forControlEvents:UIControlEventTouchUpInside];

UIButton sender title problem

seems like a quite easy problem but I don't get it.
It have two UIButtons, one is titled 'next' the other is titled 'previous'. Both are linked to the same method. All I wanna do is change the variable 'helpStatus'depending on which button is pressed:
if([sender currentTitle] == #"next"){
helpStatus++;
}
if ([sender currentTitle] == #"previous"){
helpStatus--;
}
NSLog(#"%#", [sender currentTitle]);
the logged titels are 'next' and 'previous' just like it should be but it doesn't work and I don't know why.
You need to use isEqualToString otherwise you are just comparing if they are the same object, not if they are equal :)
if([[sender currentTitle] isEqualToString:#"next"]){
helpStatus++;
}
if ([[sender currentTitle] isEqualToString:#"previous"]){
helpStatus--;
}
I would not use the string. What happens if you decide to change the label? Consider using a tag instead.
e.g. b
button.tag = 100;
...
- (void)buttonPressed:(id)sender {
UIButton *button = (UIButton*)sender;
if(button.tag == 100) {
}
}
or in your case (I am kidding, sort of), even:
button1.tag = 1;
button2.tag = -1;
...
- (void)buttonPressed:(id)sender {
UIButton *button = (UIButton*)sender;
helpStatus+= button.tag;

How to overwrite a convenience constructor the proper way?

For example I want to overwrite from UIButton:
+ (id)buttonWithType:(UIButtonType)buttonType
So I would do:
+ (id)buttonWithType:(UIButtonType)buttonType {
UIButton *button = [UIButton buttonWithType:buttonType];
if (button != nil) {
// do own config stuff ...
}
return button;
}
is that the right way? Or did I miss something? (yeah, I have been overwriting thousands of instance methods, but never class methods ;) )
So you got recursion.
Unfortunately you can not create a button with the specified type using a method other than buttonWithType. If you need to somehow initialize button after creation, you can make your own static method:
+(id)buttonWithTypeEx:(UIButtonType)buttonType {
UIButton *button = [UIButton buttonWithType:buttonType];
if (button != nil) {
// do own config
}
return button;
}