UITapGestureRecognizer makes certain fields unclickable - ios

I'm using a UITapGestureRecognizer on the lowest down view (self.view) to hide my keyboard.
UITapGestureRecognizer *tapHandler = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleBackgroundTap:)];
[self.view addGestureRecognizer:tapHandler];
And the handleBackGroundTap method simply does
[self.view endEditing:YES];
And this code works fine on most of my views except for a couple
a view where i'm using a tableview populated with clickable items (it's a list of checkboxes really)
a view that uses a datepicker (the datepicker should open when you click the textfield)
On those two views said items become unresponsive: the checkboxes are unclickable (they don't mark or unmark when tapped) and the datepicker refuses to show.
My question is: why? And: are there any workarounds?
Note: if I don't add the gesture recognizer the fields work fine but not being able to dismiss the keyboard is rather annoying.

so as I was looking around i happened to stumble across a solution (which is typical... Have been searching for days and the moment I post a question I find the solution)
In any case adding
[tapHandler setCancelsTouchesInView:NO];
solved the issue
edit: I have to wait 2 days to accept this as the answer...

Related

Custom UITableViewCell Edit View

I've been looking over countless questions and answers here on SO, but could not find one that would provide the answer for my specific problem.
In a nutshell: I am trying to implement a custom edit view for my UITableViewCells. I would like to keep the basic "delete" and "rearrange/drag" actions (although on opposite ends than in the default implementation and with custom icons), and I would also like to add a "duplicate" action to them and one that navigates to a specific view (separate from the one when you click the cell in normal state). Something like this:
Ideally, I would like to trigger this edit mode on all cells when I toggle edit mode with a separate button, and on individual cells with a left swipe (without the drag option if it is not possible on an individual cell).
I have sub-classed UITableViewCell and was able to add a swipe recognizer that reveals a view ("cellOptionsContainer") with the 3 custom buttons on the right, all of which I was able to make work using tags and delegates, but that is most certainly not the right way to do things because I've added them to the cell's content view (not knowing any better):
// Add container to hold options buttons
cellOptionsContainer = [[UIView alloc] initWithFrame:CGRectMake(cellWidth,
0.0f,
(dataBase.sizeInteraction * 3),
dataBase.sizeInteraction)];
[self.contentView addSubview:cellOptionsContainer];
// Add edit button
UIButton *cellOptionsButton = [[UIButton alloc] initWithFrame:CGRectMake((0.0f),
0.0f,
dataBase.sizeInteraction,
dataBase.sizeInteraction)];
cellOptionsButton.tag = cellID;
[cellOptionsButton setImage:[UIImage imageNamed:#"iconEditOutlined"] forState:UIControlStateNormal];
[cellOptionsButton setShowsTouchWhenHighlighted:YES];
[cellOptionsButton setAdjustsImageWhenHighlighted:NO];
[cellOptionsButton addTarget:self action:#selector(presentEditView:) forControlEvents:UIControlEventTouchUpInside];
//[cellOptionsContainer addSubview:cellOptionsButton];
[cellOptionsContainer addSubview:cellOptionsButton];
Meanwhile, I was also able to make work the standard edit view in my UITableView delegate (rearranging and deleting both works fine), but I was unable to augment this standard edit view with the added functionality and visual customization illustrated above. I cannot even find a way to change the standard icons...
Any help would be much appreciated; although, I am looking for Objective-C answers as I do not know Swift! I am also doing everything programmatically; I do not use interface builder.

didSelectRowAtIndexPath doesn't work on xCode 9

So I have to work on this really big project, it's still on objective C.
I was just ask to make a really small change (hide a button) so I did that and it's building fine and everything looks normal but then all of the tableView in the project won't react as in didSelectRowAtIndexPath is never called (scrolling work and the data are correctly displayed)
The only thing that changed compared to before is that I used xCode 9.
Now when I build it using xCode 8 it's working again so at least we can go ahead but I still am wondering what is happening.
I made a smaller project using exactly the same logic as the main project (the cell are custom, you can swipe etc)
and when I did it from scratch, it's working fine.
So I fell like it's more of an xCode bug/error than one with the code.
would someone have any idea ?
Have you used tap anywhere on that UI??
because when tap: UITapGestureRecognizer is there in UI didselect work after only at longpress of cell
or you can just set in your viewdidload function
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];
gestureRecognizer.cancelsTouchesInView = NO;
Please check the following
It should be single selection
It should be interaction enabled
And check you have created any button on top of all layers which is targeting some other action.
Check it and reply.

Accepting double and single tap in table view cells that contain a tappable label

I want to accept single and double taps in my table view cells. I also have tappable labels with hashtags in each of my cells, which I would like to remain clickable. That is a interaction that is seperate and different than what should happen when a user clicks somewhere other than a hashtag.
I noticed that depending on how I word or Google my question I get 2 different answers.
Solution A:
UITapGestureRecognizer - single tap and double tap
Its accepted answer suggests 2 tap gesture recognizers with delays, and has a high number of upvotes.
Solution B.
The other solution I have seen on several threads is implementing a tap counter in tableView:didSelectRowAtIndexPath: combined with a short timer. There are a lot of these threads with this as the accepted answer, but none of them have anywhere near as many upvotes as the answer from solution A.
Is there any argument for why one is better than the other?
The problem here with both solutions is that gestures suck up my attributed labels' taps, and the ...didSelectRow... solution prevents users from tapping multiple cells rapid fire without issues; it is sloppy and leaves room for error.
you can have 2 Gestures.
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onClikOneTap:)];
tapGesture.numberOfTapsRequired = 1;
AND
UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onClikDoubleTap:)];
doubleTapGesture.numberOfTapsRequired = 2;
With magic Line for control
[tapGesture requireGestureRecognizerToFail:doubleTapGesture];
This has worked very well for me on many occasions.

Forwarding a gesture to superview

So I have got this scenario:
-NavigationController
-PageViewController
-MapViewController
-UIView
-MKMapView (Full Screen)
-OtherViewController
So basically, I want it to switch pages (viewcontrollers) when catching the UIScreenEdgeGesture. But having the map in one of them, this doesn't work properly.
I have researched a lot (!) about this but still haven't found the right solution.
I believe that the correct approach here is to delegate this gesture to the nextResponder in the hierarchy.
So I have successfully captured the gesture when the user swipes on the left edge of the screen.
Right now my issue is I can't manage to pass the gesture to the UIView (MKMapView.superview).
I have two questions :
// 1. How to do it
// 2. Is this the right approach?
Let me know your thoughts on this one please!
EDIT 1:
Adding some code and Images of story board
UIScreenEdgePanGestureRecognizer *popRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:[self.view superview] action:#selector(handlePopRecognizer:)];
popRecognizer.edges = UIRectEdgeLeft;
popRecognizer.delegate = self;
[self.mapView addGestureRecognizer:popRecognizer];
EDIT 2: I want this behaviour : Use UIScreenEdgePanGestureRecognizer without moving MKMapView
But when the gesture is recognized, I want it to switch to the page on the left (OtherViewController)
FINAL EDIT: THE workaround that I've come up with consists in putting a clear view on top of the map, leading to the desired behaviour. Not happy with the solution, but it works for now.
When you create your gesture, make the target the superview, and call the method in the superview for the action, something like:
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:[self.view superview] action:#selector(swipeHandler:)];
Don't know if MKMapView.superview would work, that depends on if MKMapView is an instance. Hard to know what you're referring to without code.

Unexpected UIPageViewController behaviour

I'm currently building a app using UIPageViewController. It is working as I expected until it reaches last page which contains numbers of UITextField.
But when I tapped one of instances of UITextField, it suddenly jumps to the previous page without any reason instead of showing a keyboard. When I scroll through to the last page and tap a text field again, it works well without any problem.
It is also fine when it shows last page immediately by tapping the navigation button that links to the last page and that is attached to the UIPageViewController instance.
This problem happens only when I scroll through pages from first to the last, and it happens only once at the first try.
I suspected low memory issues, so I set breakpoints in -didReceiveMemoryWarning method of both UIPageViewController instance and the last page view controller. But they were never called.
The second try is that I added a breakpoint in the last page view controller's -willMoveToParentViewController: method and set its condition to parent == nil(when it's removed from parent view controller, which is the UIPageViewController instance in question)
When I run the app, the breakpoint's call stack says that the method is called by UIPageViewController's -_flushViewController:animated:.
I don't know why this -flushViewController:animated: is called. If I can figure out the cause, it will help me with fixing the problem.
Is there anybody who can help me?
I'm not sure what it is in your code that does this, but one probable approach in debugging this is to try and catch the UITextField's UIKeyboardWillShowNotification event to check if it's firing properly.
Also try to set a breakpoint at your page's viewWillAppear event to inspect if all of the UITextFields have been instantiated properly -- I would suspect that at the point where you tapped the first text field not all of them have instantiated yet, meaning that the object receiving the tap action will be your UIPageViewController instead of the UITextField.
I found the answer here:
Cannot Impliment UITextview inside a UIPageViewController
Credit goes entirely to him.
I can confirm that it works. Here is what I did in my view controller:
//TextField
UIScrollView *textFieldScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, width, height)];
[textField setText:#""];
[textField setBackgroundColor:[UIColor whiteColor]];
[textField.layer setCornerRadius:5.0f];
[textField setDelegate:self];
[textFieldScrollView addSubview:textField];
[_someView addSubview:textFieldScroll];
Works like a charm. Let me know if you have any more questions.

Resources