Multiple tap on UIButton and access different behavior of Button - ipad

I create a project of the Multiple user can tapped on the different button.
Following problem may phase,
I implement the gestureRecognizer and it's proper work but how get the which button tapped by the user for that to access those button event's
following screen shows the button,
Following is the code for gestureRecognizer delegate method so, how to get the button event and how to manage it,
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([touch.view isKindOfClass:[UIButton class]]) {
NSLog(#"Button is pressed");
if (tag == 1) {
NSLog(#"Button1 is pressed");
}
return NO;
}
return YES;
}
following method for the IBAction method to touch when the button tapped
-(IBAction)btnPress:(id)sender{
tag=[sender tag];
NSLog(#"%i",tag);
}
But here issue is first call the gestureRecognizer delegate method then IBAction method to how to solve this problem,
Thanks in advance for your valuable time spend on my problem,
Thaks and regards
Neon Samuel.

If the button is instance of UIButton, then you do not need to use gestureRecognizer at all.
Try to set addTarget:action to get callback when user click that UIButton:
[button1 addTarget:self action:#selector(btnPress:)];
[button2 addTarget:self action:#selector(btnPress:)];
If you have already set tag value to each button, then your IBAction method would work properly.
-(IBAction)btnPress:(id)sender{
NSInteger tag=[sender tag];
NSLog(#"%d",tag);
}

Related

Deselect a button in a table view cell when another is tapped

I have a table view with user posts that can be upvoted and downvoted. I have two custom buttons for the upvote and downvote in the cells, which I use like so:
// in cellForRowAtIndexPath:
[cell.upVote addTarget:self action:#selector(handleThumbsUp:) forControlEvents:UIControlEventTouchUpInside];
[cell.downVote addTarget:self action:#selector(handleThumbsDown:) forControlEvents:UIControlEventTouchUpInside];
//the methods
- (IBAction)handleThumbsUp:(ThumbsUpButton *)sender {
if (sender.selected == YES) {
[sender setSelected:NO];
} else {
[sender setSelected:YES];
}
}
- (IBAction)handleThumbsDown:(ThumbsDownButton *)sender {
if (sender.selected == YES) {
[sender setSelected:NO];
} else {
[sender setSelected:YES];
}
}
When the "Thumbs Up" button is selected, and the user changes his mind and presses "Thumbs Down", how can I deselect the "Thumbs Up" button in that same cell?
You should have a model that contains the "thumbs up/down" information; you should not be storing it in your views in the form of the button being selected or not.
When one of the buttons is tapped, your controller should update the model and refresh the view based on the state of the model.
(Some kind of binding system would make this easier: ReactiveCocoa is one such option (though it's much more than just model/view bindings); another, much simpler (shameless link to my own free code) is my own UIViewController+WSSDataBindings category.)
By #selector you can access a property of the button not another control of the cell in a button handler method.
So, You must have update whole cell on the button handler method and manually handle the selected state of buttons in cellForRowAtIndexpath delegate method of table.
For simplest solution (with minimum structure change and code) it may be achieved with moving button action methods to your custom cell class. then add actions to upvote and downvote in cellForRowAtIndexPath:
// in cellForRowAtIndexPath:
[cell.upVote addTarget:cell action:#selector(handleThumbsUp:) forControlEvents:UIControlEventTouchUpInside];
[cell.downVote addTarget:cell action:#selector(handleThumbsDown:) forControlEvents:UIControlEventTouchUpInside];
Or you can directly set this methods from Nib file.
and then change the upvote / downvote methods like this.
//the methods
- (IBAction)handleThumbsUp:(ThumbsUpButton *)sender {
if (sender.selected == YES) {//upvote undone
[sender setSelected:NO];
} else {//upvote done
[self.upVote setSelected:YES];
[self.downVote setSelected:NO];//delesect downvote
}
}
- (IBAction)handleThumbsDown:(ThumbsDownButton *)sender {
if (sender.selected == YES) {//downVote undone
[sender setSelected:NO];
} else {
[self.downVote setSelected:YES];
[self.upVote setSelected:NO];//deselect upvote
}
}
also as Josh Caswell stated in his answer, you should have a data for the user's upvote and downvote in your dataModel you fill your cell. This is just a quick answer for this specific case, but to support dataModel changes you can add reference to your model inside your cell and modify it inside this action methods for saving votes.

How to add tap gesture on button inside UItableCell in iOS?

I have made a custom cell.In each custom cell there are many button like 3 to 4 i want add tap gesture for each button inside that cell.So that i can uniquely identify which cell's button was clicked.I have searched a lot but didn't find any good solution.
Please tell.
you want to access the button you can directly access, no need of Gesture
do like
[yourButton1 addTarget:self action:#selector(selectButtonPressed1:) forControlEvents:UIControlEventTouchUpInside];
yourButton1.tag=indexPath.row;
[yourButton2 addTarget:self action:#selector(selectButtonPressed2:) forControlEvents:UIControlEventTouchUpInside];
yourButton2.tag=indexPath.row;
[yourButton3 addTarget:self action:#selector(selectButtonPressed3:) forControlEvents:UIControlEventTouchUpInside];
yourButton3.tag=indexPath.row;
[yourButton4 addTarget:self action:#selector(selectButtonPressed4:) forControlEvents:UIControlEventTouchUpInside];
yourButton4.tag=indexPath.row;
Method - 1
-(void)selectButtonPressed1:(UIButton*)sender
{
NSLog(#"selcted button1");
}
Method - 2
-(void)selectButtonPressed2:(UIButton*)sender
{
NSLog(#"selcted button2");
}
Method - 3
-(void)selectButtonPressed3:(UIButton*)sender
{
NSLog(#"selcted button3");
}
Method - 4
-(void)selectButtonPressed4:(UIButton*)sender
{
NSLog(#"selcted button4");
}
Lets say you have n number of buttons. And you have one butotn action method:
YOu need to connect this method to all of your n buttons (touch up inside), so that whenever you press a button, this method will get hit.
You can either give tag values for your buttons or you can recognise them by thier title
-(IBAction) nButtonActions:(id)sender{
if([[sender titleLabel] isEqualtoString:#"your button-1 title"]){
//call your method for button -1
}
//or you can do the same using sender.tag
}
use restoration identifier.
button.restorationIdentifier = #"Cell Number _ button tag";
for example
button.restorationIdentifier = [NSString stringWithFormat:#"%#", indexPath.row];
NSString* rowIndexStr = ((UIButton*)sender).restorationIdentifier;

UIButton not registering on ios7

I have a button, it works as usual on iOS 5 and 6. But on iOS 7 when I press the button the keyboard dismisses, but the method is not called. When I press it second time it works as intended.
Why is that?
Here is the code:
[self.loginButton addTarget:self action:#selector(loginButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
I have the button in UITableView cell.
EDIT:
Here is how I dismiss keyboard at the beginning of this method, but this method is not getting called o iOS7 until the second time I tap on the button.
for (UITextField *field in #[self.loginField, self.passwordField]) {
if ([field isFirstResponder]) {
[field resignFirstResponder];
}
}
I also have gesture recognizer to remove keyboard on tap outside:
UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(removeKeyboard)];
[self.view addGestureRecognizer:tapper];
tapper.cancelsTouchesInView = NO;
Here is its method:
- (void) removeKeyboard
{
[self traverseAllSubviewsOfView:self.view withBlock:^(UIView *inView) {
[inView resignFirstResponder];
}];
}
Here is what helped me - I set controller as delegate for gesture recognizer and implement following method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// test if touch is on button
if ([touch.view isKindOfClass:[UIControl class]]) {
return NO;
}
return YES; // handle the touch
}
Did you check the cancelsTouchesInView property of the gesture recognizer? This property controls if touches are delivered to any underlying views. So settings this to NO should allow the touch to be sent to your button. More detail here.
This property can be set in code or in Interface Builder. You can set it in IB by highlighting the gesture recognizer and uncheck "Cancels Touches in View" (I think) in the Attributes Inspector.
I'm not in front of a Mac currently so I can't confirm the exact wording.

How to make a START/STOP button for an iOS app

just wondering how to make a button "START" that when pressed triggers a function and the text changes to "STOP". then when pressed again the function will stop and the text changes back to "START"
Ive got the button already that starts the function. and i can handle changing the title, just not sure on what to use to make the 1 button have 2 functions
Add the IBAction method like:
- (IBAction)buttonTapped:(id)sender
{
UIButton *btn = (UIbutton *)sender;
NSString *title=btn.titleLabel.text;
if ([title isEqualToString:#"Start"])
{
//Start
}else
{
//Stop
}
}
Please try this:
- (IBAction) buttonAction:(id)sender
{
if([[(UIButton *)sender currentTitle]isEqualToString:#"START"])
{
[actionButton setTitle:#"STOP" forState:UIControlStateNormal];
//start the action here and change the button text to STOP
}
else if([[(UIButton *)sender currentTitle]isEqualToString:#"STOP"])
{
[actionButton setTitle:#"START" forState:UIControlStateNormal];
//stop the action here and change the button text to START
}
}
you have at least two options here:
Check for the title of your button and depending on the value call an action or the other.
Create two different buttons, each one with his action and show/hide them.

UITableView - resign first responder on outside touch

I have a UITableView with an associated UITableViewController. However, I've modified the table to also have a view with a textfield subview.
As always, I want the keyboard to disappear when the user hits 'done' (easy) and when they touch anywhere else on screen other than the textfield (hard, stuck!).
The normal way to achieve this is to change the class to UIControl so it can handle actions... but I can't do this for my UITableView/UITableViewController combination.
How can I solve this problem?
U can handle user touches by adding a UITapGestureRecognizer to your view.
For example if u don't want to enable row selection in your tableView u call self.tableView.allowsSelection = NO;
But if u still want to detect user touches u add a UITapGestureRecognizer to your tableView (or to tableView.superview).
U can have more control if u implement the UIGestureRecognizerDelegate, this way u can detect and then choose witch touches to receive and witch not.
To do that just add this code to your UITableViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.allowsSelection = NO;
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(viewTapped:)];
tgr.delegate = self;
[self.tableView addGestureRecognizer:tgr]; // or [self.view addGestureRecognizer:tgr];
[tgr release];
}
- (void)viewTapped:(UITapGestureRecognizer *)tgr
{
NSLog(#"view tapped");
// remove keyboard
}
// this is optional, it let u choose witch touches to receive, for example here I'm checking if user has tapped on a textField
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UITextField class]]) {
NSLog(#"User tapped on UITextField");
}
return YES; // do whatever u want here
}
A normal practice is to put a custom UIButton( it becomes visible only when uitextfield begins editing ) behind keyboard view, and when user clicks on screen he actually clicks on that button, and associated selector can resign first responder.
-(void) closeKeyboard:(UIButton *) b {
[self.view endEditing:YES]; //assuming self is your top view controller.
[b setHidden:YES];
}
Using endEditing is better, cause it loops through all subviews and looks for current first responder.
Using alloc breaks with ARC enabled
Just add the following to the viewController
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//where text field is a #property (nonatomic,retain) IBOutlet to your textfield
[textField resignFirstResponder];
}
When a row is tapped the didSelectRowAtIndexPath is called. If a textField located inside inside a row is tapped then the textfield delegate is called.
So in addition to your done button method, in didSelectRowAtIndexPath add a check for the text field being first responder and ask it to resign. Assuming a the selected indexPath is not the row of the textfield.

Resources