How are touches handled by a UITableView? - iphone

I'm trying to better understand how UITableView and UITableViewCell work, and one part of that is touch handling.
So when I touch a row on a table view, what exactly happens? My basic understanding is:
UITableView is a UIScrollView, so first it checks if it's a touch or a scroll
If it's not a scroll then the touch gets analyzed to see which row is under the touchpoint
It gets the cell at this indexPath (how?) and tells it to setHighLighted, setSeletected
Is that it? Does anybody have a more thorough understanding of it than that?

Probably somethign along the lines you mentioned, you never know though until you see t he source, why do you want to know anyway? you making your own tableview?

One last step is that the touch gets passed to the cells content view. That way any subviews in the cell will receive touch events. I'm pretty sure this comes after your step 3 and actions from cell selection will be processed first.

Related

Drawing UITableViewCells for fast scrolling, but what about links?

I read this great article from Twitter about fast scrolling and how to draw cells. I have implemented this fine, but now the hard part - the links in the tweet. Is there any way to use this approach and draw links in the cell as well? I know this is possible using a number of different label extensions, but the article specifically mentions not using UILabels and UIImageViews. If I have to use UILabels to achieve this that's fine. I just want to be sure this is the only way. Thanks.
Because detection of touch events is done in UIViews, one method might be to override the UITapGestureRecognizer on the UITableViewCell, and in the action it fires upon a touch, check to see if the tap is within the bounds of your link that was drawn. If it was, handle it accordingly, if not, handle it as a cell selection.
If you don't need cell selection, you could always have selection of a table cell perform the action you want for the link as well.

custom uitablviewcell does not call didSelectRowAtIndexPath in the controller

I have a custom UITableViewCell completely written in code (no IB), it has an accessory button that simply calls didSelectRowAtIndexPath on the table view, and it works correctly and the method is called without problems.
However, when I tap on the cell itself (not on the accessory view) nothing being called, why ?
EDIT: the code is huge to put here ... however, the custom cell contains a ton of labels, couple images and scroll view ...
This is a shot in the dark, but if each cell has many different objects on it (i.e. images, labels, etc) then it may not be working because those objects are what the user is hitting when they try to click a cell. Does the cell turn blue (indicate selection) at all? If not, try hiding/removing those objects for now and see if it works.
If that is the case, then what you may want to do is create an invisible cell or button that sits on top of the other objects and calls didSelectRowAtIndexPath from behind the scenes.
This should solve your problem:
Raise selection event (didSelectRowAtIndexPath) when subview of UITableViewCell is tapped
Try setting your view's userInteractionEnabled property to NO.
This will make it ignore all touch events, and then the views under it will be able to catch these events. - Felipe Sabino
I'd partially answer my question: the wide scroll view is preventing the cell from calling didSelectRowAtIndexPath, removing the scrollView will solve the problem, however, I want to call this method with the existence of the scrollView ... anyone got ideas would be highly appreciated ...
You must post your code to understand what have you done...You have to check out this example to understand whether your code is correct or not...
http://www.edumobile.org/iphone/iphone-programming-tutorials/impliment-a-custom-accessory-view-for-your-uitableview-in-iphone/

backgroundView for a UITableViewCell that is being reordered?

I'm trying to change the background view for cells that the user starts to drag with the handle out on the right hand side.
Apparently the selectedBackground view is not used in this state, is there any other solution?
This seems to be a tough one. It doesn't seem as if Apple has provided a way to notify the developer that the user has started reordering a table view cell. So I think this is what you'd have to do:
Subclass UITableViewCell.
Override the touchesBegan et al methods (this might get you started: http://devblog.wm-innovations.com/2010/03/30/custom-swipe-uitableviewcell/)
If you detect a "drag" touch event and the cell's showsReorderControl property (see http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html) returns YES, swap out the backgroundView, remembering the previous one.
When the touch event ends, restore the old view.
Realize that it's not as easy as above 4 steps.
Custom touch handling inside a tableview is possible but hard. You might have to temporarily disable touch events in the UITableView (climbing up the responder chain) to make this work.
I hope these pointers get you moving in the right direction, though.

Any ideas on how to make a UIPickerView from scratch?

I've decided that I don't want to ever use UIPickerView again... it's completely inflexible in terms of functionality, design, and size (height). It also occasionally gets stuck between rows, and the delay that occurs between letting go of a wheel and when the delegate method is fired indicating that a new row has been selected (because of the "settling in" animation) has caused lots of problems in the context of the apps I've been working on.
That being said, the user-friendly aspects of UIPickerView are good, and I'd like to try to replicate it. I've tried to research different ways that this might be done, but without much success. Does anyone have any ideas as to what would be involved to make something similar from scratch?
I was trying to get a UITableView subclass to behave in such a way that whatever cell was currently in the middle of the table (it would change while dragging, etc.) would change its background colour to something different implying that it was "selected". As soon as the table was dragged such that the "selected" cell was no longer in the middle, the cell would go back to normal and the new middle cell would change colour. So this would be like UIPickerView in a sense that you don't have to tap on a cell; instead you just drag to have one selected by default.
I figured it should have been easy enough to intercept the "touchesMoved" method of UITableView and add some code that looped through all currently viewable cells in the table, checking to see if their frames overlapped the center point of the table, and changing their appearance accordingly (plus sending a notification to other classes as needed to indicate the "selection" change). Unfortunately, I can't get this to work, as the "touchesMoved" method doesn't get called when I drag the table. Am I missing something obvious?
Any ideas or suggestions would be very much appreciated at this point... I made an app that relied heavily on UIPickerView objects, and because of the problems I've run into with them, I'll have to abandon it unless I can figure out a way to make this work.
Thanks very much,
Chris
Remember that a UITableView is a subclass of a UIScrollView, and the UITableViewDelegate gets all the UIScrollViewDelegate method calls too. scrollViewDidScroll: sounds like it would easily fit the bill for knowing when the table view was scrolled.
As for finding which row is in the middle of the view, just use indexPathForRowAtPoint:.

How to determine if scrolling a UITableView was done by tapping the index?

I want to determine when the index (transparent alphabet) along the side of a UITableView is tapped. To be more specific, I have a sectioned UITableView that has an index, and said index does the right thing, but when the UITableView's -scrollViewDidScroll method is called, I want to be able to determine if said scrolling was the result of the user tapping the index, vs. dragging or swiping the table view itself. If anyone has ideas on how to do this, i'd love to hear about them :-)
Regards,
John
You could override touchesBegan to monitor the location of any touch event that precedes scrollViewDidScroll.