Touch Down firing in a weird way - ios

I'm adding a touch down action to a uitextfield (actually it's a subclass, but I think that might not be important). I created a simple view controller and added this textbox to it, and wired up the event to println("Hello").
When I quickly tap the item (both in simulator, and on my phone) it works perfectly and says hello!
I then created a UITableViewController subclass, and in one of the static cells I added the same textbox.
In this case, when I quickly tap the textbox nothing happens! When I actually hold down the mouse or my finger for about 1/2 a second, it works. But not if I quickly tap it.
This is different from the previous textbox, which always works perfectly no matter how fast I tap it.
Are there some problems with different events being intercepted ors something of that sort?
I even went so far as to add a tap gesture recognizer to both the table cell, and the textbox, but neither work unless I hold it down (the table cell action won't even fire unless I click off the textbox and into the cell proper, of course).
Thanks so much this is very strange.

UIButton not showing highlight on tap in iOS7
and
iOS - Delayed "Touch Down" event for UIButton in UITableViewCell
have a lot of information about this. Apparently there is a delay for uitableviewcells that can be avoided by taking some of the approaches above.
I'll post the solution that works for me once I work on it. thanks!
EDIT OP DID DELIVER!! (lol sorry)
in IOS8, the idea is that table cells no longer have the uiscrollview that would basically delay the touching, so what you can do instead is something like this in your page did load:
for subview in self.tableView.subviews as [UIView]
{
if subview is UIScrollView
{
let scroll = subview as UIScrollView
scroll.delaysContentTouches = false
break
}
}
So see how we're iterating over self.tableview's subviews, and anytime we hit a scrollview set delaysContentTouches to false. This worked for me on both the simulator and on my phone.

Related

Conflict with a UIPanGestureRecognizer on a UITableView's superview

I'm trying to build something roughly similar to the drawer menu in Apple Maps on iOS.
In this Xcode project I'm attaching a UIPanGestureRecognizer on the VC's view, and as the panning happens, move vertically a UITableView with scrolling disabled.
The issue is every time after the pan ends, the didSelectRow method is called only after a second tap happens somewhere on the UITableView. Of course I'd like it to be called after the first tap.
The funny thing is that the bug does not happen if I enable the table's scrolling, and in the gesture recognizer's delegate have shouldRecognizeSimultaneouslyWith returning true.
Other funny thing is a very similar thing seems to happen in Apple Maps itself, if you try pulling the drawer up with the finger resting on a recent location entry from the list inside the drawer.
Thanks for your help!
I don’t understand well what are your saying.
But I think that the main problem is with “Chain Responder”. When you use PanGestureRecognizerand the UITableView property isScrollEnable = false in the Responder Chain the PanGestureRecognizer it is the first who is called, and the system wait to that fails or the event is not handled, then it is passed to the next in the Responder Chain, who is the UITableView. For that reason, it takes too long to get called the didSelectRow function
I suggest to you create a new UIView and insert in the ViewController in the storyboard o nib and put the UITableVIew outside of that UIView, then link the PanGestureRecognizer to that new UIView. In that way the Responder Chain don’t get in conflict with both, because the system can detect when the drag is in the new UIView and call only to the PanGestureRecognizer and when it is in the UITableView will call to the didSelectRow
Best Regards
Write if it does not resolve

UIButton default tap animation inside UITableViewCell

I have a few UIButtons inside UITableViewCells, and all of them are missing default tap animation, however if I long press - animation works. I've found some solutions, like setting type to .system, showsTouchOnHighlight = true, but none of them have helped. What is the problem here?
It's not a "problem" - it's by design.
When you have an object such as a button in a table view or scroll view or collection view, and you "touch" it, the system needs to know whether you are tapping the button or if you want to touch-and-drag to scroll the view that contains the button.
So, the table view (really, the "scroll view part" of the table view), waits to see if you drag your finger or not before it performs any actions.
If you want the button to respond immediately to a touch, you need to set
delaysContentTouches = false
on the containing scroll view(s).
If you search for uibutton inside uitableviewcell delaysContentTouches you should find plenty of discussion on this topic, and various approaches to change the default behavior.
For this problem you can add extension to UIButton and override some methods.
You can check my answer here

Touch Down/Up and Scroll in UITableViewController

I'm having a bit of of a pain point in figuring something out.
I have a uitableviewcontroller, and each cell is static. Inside each cell is a textbox. When the user TAPS on a textbox, I'd like an event to fire.
So while I'd like my table to still scroll, i'd also like tap events to work when you tape the textbox.
Apparently in uitableviews, they add a delay to your tap so you have to hold your finger down for a second or so for 'tap' to register. I felt this was not intuitive to a user, so I did this to fix it:
for subview in self.tableView.subviews as [UIView]
{
if subview is UIScrollView
{
let scroll = subview as UIScrollView
scroll.delaysContentTouches = false
break
}
}
This works perfectly, and now when I tap my textbox, it instantly executes my tap event! The problem now, however, is some of my textboxes are positioned right where a user would naturally scroll. When they put their finger down (touch down event) to scroll, it's unfortunately being intercepted by the tap event, and prevents scrolling and instead executes my event.
What i'd really want is if the user puts their finger down, and then swipes, it doesn't execute the touch down event. I thought to be clever and switch touch down to touch up, but when I put my finger down and then pick it back up, it does nothing (touch up inside seems to do nothing). I read this was because it only works on buttons and things like that, and not textfields. So, yes, now I can scroll without my action, but when I tap the textbox and lift my finger up it doesn't execute that, either.
Any ideas on how to either
1) permit touch downs and scrolling to co-exist without having to hold my finger down for a second and deal with that delayContentTouches?
2) somehow get a tap up inside event to fire when I tap on a textbox?
I saw some info here but didn't seem to help much:
UIButton inside UITableViewCell steals touch from UITableView
Thanks!
Well, as luck would have it, I was able to figure this out. Would love some criticism/advice if something might not be ideal here, but what I did was add this to my subclassed textfield:
override func canBecomeFirstResponder() -> Bool {
performMyFunctionHere()
return false
}
So I am returning false on first responder which prevents any sort of keyboard appearing (which is what I wanted) and instead using performMyFunctionHere() I can do what I wanted to do (in my case, make an action sheet picker appear). I assign the action sheet picker in my view controller and assign it to each specific instance of my subclassed uitextfield. Nothing really complicated, to be honest. I'm surprised this works as well as it does.
By the way one thing that didn't seem extremely important was setting the delaysContentTouches as I mentioned above. I guess because now it's using the responder it will always work? It didn't seem to matter whether I removed it or not, but would love thoughts on whether it's better to leave it in or not.
Thanks!

Unable to Interact with UISearchBar in a UITableView

The Issue
I have a UIGestureRecognizer setup that on press to any of the UITableViewCell in my UITableView, it sets the UISearchBar active. Everything works. I can press on the cell and the UISearchBar animates as it would normally. I can enter letters, tap and hold on the UITextField and zoom in to a specific cursor position. I can hit cancel and everything goes back to their proper locations.
This is where the issue comes up. I scroll down a few cell (or until the UISearchBar is hidden under the UINavigationBar) and press the cell to activate the UISearchBar. Everything seems to animate to their proper location but when I try to tap and hold to zoom in to a proper cursor on the textfield nothing happens. I am also unable to hit the cancel button. The odd part is that if I do press on any part of the UISearchBar, it becomes the first responder.
Things I have done
I played around with the contentInset of the searchResultsTableView and see if that was blocking the UISearchBar.
I played around with the frame of the searchResultsTableView and its superview to see if it is blocking the UISearchBar.
I added the methods defined in the UISearchDisplayDelegate protocol and ensure that there were no views blocking said UISearchBar.
Please help!
My goal is to be able to interact with the UISearchBar as it is intended. If you know of any other option I can please let me know!
Thank you in advance!!
Update
I found the answer at Programmatically activating UISearchBar blocks user interactions with it
There is a possibility of a timing issue when the UISearchBar is shown and when it becomes active so the solution is to delay activating it.
So when you scroll down, the tableview is actually not referencing to the original cell as a result of the way iOS tries to reuse cells to conserve memory. The way to solve this is to say if(indexPath.row==0){cell.contentview addGesture...} in the cellForIndexPath function or use the didSelectAtIndexPath function to specify what happens when you click indexPath.row 0

iOS: Tapping on UITableView does not call didSelectRowAtIndexPath

My app uses a UITableView with a UINavigationController to show a more detailed view when a row of the table is tapped - the basic drill-down routine.
When I tap on a row, it is highlighted, but the delegate methods tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath: are not called (verified using debugger).
Now here's the weird part:
There are some other table views in the app (they don't drill down) and none of them exhibit the issue.
If I tap the row rapidly and repeatedly, after many tries (10 - 20 is normal), tableView:willSelectRowAtIndexPath: and tableView:didSelectRowAtIndexPath: are called and processing continues normally.
The problem occurs only on an (any, actually) iPad running iOS 6. It works fine with iPads running iOS 5, or with any iPhone running any iOS version, 6. It also works with the iPad simulator using iOS 5 or 6.
So it seems that something is receiving the tap before the delegate methods are called. But what?
I not using any UITapGestureRecognizer, so that is not the issue.
I am not using multiple UITableViewControllers for the table, so this is also not the issue.
I was having this issue with an app when running in iOS6. The tableView:didSelectRowAtIndexPath: method was never being triggered, even though it was working before updating to iOS6.
I finally figured it out by looking at the xib and the attribute inspector for the table. In the Table View section I had the Selection option set to No Selection and Show Selection on Touch was not selected.
Changing the Selection option to Single Selection actually got this working for me again and leaving the Show Selection on Touch unselected means that I don't see any flash or change of colour when the row is selected.
I encountered a similar issue. iOS 6 appears to be much more sensitive to the slightest upward movement on a tap on a table view cell. It appears it is registering the slightest movement as a scroll request rather than a cell selection. My table view was set to scrollEnabled = NO because it is a table view with static selection values. The table view appears within a small area of a larger iPad view. If I carefully tap a cell and lift directly up, the cell is selected.
To resolve it, I changed scrollEnabled to YES and made sure the area dedicated to my tableView was larger than the actual area needed to show the table view, thus preventing it from scrolling. Not sure if this is is the cause of the issue you are experiencing, but hope it helps.
I had the same problem. The UITableView was not triggering the didSelectRowAtIndexPath method when running in iOS6, but it was working fine in iOS5.1.
I had also implemented the
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{
return NO;
}
and returned NO. In iOS5 it was all working fine, but the minute I switched to iOS6 it would cease to trigger the didSelectRowAtIndexPath. Once I removed that shouldHighlightRow method, everything worked in iOS6 again. Cheers!
The usual reason that didSeletRowAtIndexPath() doesn't get called is having a UITapGestureRecognizer on your viewcontroller with Cancels touches in view set to YES.
The correct and only sensible fix is to set Cancels touches in view to NO. Then your table row selection should work nicely.
Obviously this has some implications in your gesture handlers - you may need to add some code to your gesture handler to stop some touches going on to your views i.e.
- (IBAction)onTapGesture:(UITapGestureRecognizer *)sender {
if (sender.view == someOldViewThatINeedToDealWith) {
sender.cancelsTouchesInView = true;
}
}
I tried all the other answers posted, and although they seemed promising, they didn't solve the problem.
I've since discovered the cause of problem in my case: I was calling [self.tableView reloadData] on a different thread (due to handling an NSNotification event posted from a background worker thread).
I fixed the problem by changing [self.tableView reloadData] to
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
Hope this helps.
The other suspect could be a Tap Gesture Recognizer set to the view controller's view swallowing all taps like a blackhole. Remove the gesture recognizer will enable did select. I just had the same issue and the tap gesture was the cause.
The resolution is really weird: the UITableViewController registered for all notifications. In the handler for the notifications, the table view data was being reloaded using
[self.tableView reloadData]
According to Apple DTS, when the table reloads data, this causes a notification to be sent to the observer, causing a race condition ...
No explanation for why it would work sometimes or why it would always work on an iPhone. But registering only for a small subset of notifications (i.e. the ones I was really interested in) fixed the problem!
Setting
recognizer.cancelsTouchesInView = NO;
takes care of it if your use case allows simultaneous handling
of touches by [tap] gesture recognizer (kdb dismiss for example)
and the view the recognizer is attached to.
in my case I hade button which received all touch events before tableviewcell

Resources