How to enable didSelectRow on selecting an element included inside the cell? - ios

Well I have gone through web to search an easy implementation of this question but all I heard is coincide with what I thought at beginning which is not easy enough.
I was wondering if anybody could provide a better and easier implementation to solve this issue.
Well looking at the picture below, (Please neglect the crudeness of the picture)
I have a table view with multiple cells.
And based on the data, there will be different element(s) inside each cell.
If I touch inside the scrollview in cell 2 as shown in the picture. The delegate method for the tableView "didSelectRowAtIndexPath" will NOT be called, which is a problem for me.
So my first thinking is either to trigger the [tableView selectRowAtIndexPath] within the Scrollviews delegate method or I attach another tapGesture to these subviews and trigger it from there. But it already doesn't sound like a intuitive implementation and hard to maintain.
Anybody got any idea how could this be solved in an easier way?
Thanks

There are a wide variety of objectives you might be trying to accomplish here, so I won't speculate on the ultimate goal which you haven't told us, but in general:
If you would like two different UIElements to execute the same chunk of code, then you encapsulate that code in a stand-alone method, and call that method from both places.
In your UIScrollView as a subview of a UITableViewCell example, you would call it from within -(void)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath and you would also call it from the gesture recognizer that you attached to your scrollView.
I will speculate that the part you're having trouble with is knowing which scrollView was touched, or which row the scrollView was in. One possible approach would be to send the UIScrollView or the UITableViewCell as a parameter for the standalone method you created. -(void)doSomethingSpecialWith:(UITableViewCell*)cell or -(void)doSomethingSpecialWith:(UIScrollView)view
Post some more code, or feel free to explain your agenda further, but I have a strong feeling that the best way for you will be to subclass UITableViewCell, add the UIScrollView as a property of the custom cell, and wire up the gesture recognizer to call a method of your subclassed UITableViewCell.

i think the better way to solve this problem is :
creat custom method , - (void)tableviewSeletedIndexPath:(NSIndexPath *)indexPath
you can call this method in TableViews delegate -(void)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath , and call this method in your scrolls method.

Make the tag of scrollView is equal to the current cell row:
scrollView.tag = indexPath.row;
Make your ViewController to be the delegate of UIScrollView and in didScroll get the index and call didSelect:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSIndexPath *index = [NSIndexPath indexPathForRow:scrollView.tag inSection:0];
[self tableView:self.tableView didSelectRowAtIndexPath:index];
}

Related

UITapGestureRecognizer in UITableViewCell are not recognized

I made a quite a bit customized UITableView which has 3 rows, each row is custom made using UITableViewCell. I added several UIViews within UITableViewCell along with UITapGestureRecognizers.
Due to many small views in UITableViewCell, I implemented codes for touch events on "m" file of that UITableViewCell.
Somehow the recognizer are not working. I am not sure I am providing enough info here..
UPDATE: I realized my explanation isn't quite enough.. so a little more detail.
This is how my UITableView look like,
UITableView has UITableViewCell(A).
UItableViewCell(A)'s contentView is made by combination of 6 other UITableViewCells(B).
Each UITableViewCells(B) has a few UIViews which have those TapGesture recognizers.
I know it seems over complicated, but I used UITableViewCell(B) not for reuse purpose but for repeated Nib files. Anyway the final UIView doesn't take any touch events.
UITableView has its own tap gesture for selecting the row. You can do it by implementing your code inside following functions. Can you tell me what are you using to implement for selecting the row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}

How to access parent object in Objective C

I am creating a Custom UITableViewCell with a UITextfield in it, I would like to know how to access the the custom UItableViewCell from the UITextField delegate didend?
I am trying this
- (void)textFieldDidEndEditing:(UITextField *)textField {
CustomFinishingCell *updateCell = (CustomFinishingCell *)textField.superview;
but that's not returning a UITableViewCell, I think it's returning the UItableScrollView or something like that.
The textField's superview will actually be the cell's contentView. You could probably get the cell by doing:
CustomFinishingCell *updateCell = (CustomFinishingCell *)textField.superview.superview;
That's a little clunky though.
I also wouldn't recommend using tags as that's even more clunky.
What I would do, is create a subclass of UITextField with a property for your CustomFinishingCell and set that when creating the cell (where you add the UITextField). That will ensure everything keeps working, even if the user resorts the cells, adds/removes cells etc, and will work well with cell reuse.
Update:
In a lot of cases, it will be better to actually use #TimReddy's answer and set the delegate of the UITextField to the CustomFinishingCell and move the - (void)textFieldDidEndEditing:(UITextField *)textField etc code to that subclass. That will save you having to create another subclass for UITextField.
You need to have your custom UITableViewCell be that UITextView's delegate. That way you know for certain when the delegate fires it is that UITableViewCell's text view.
You may need to so some cleanup work before the UITableViewCell gets recycled tho.
You could give each cell view a tag, then call UIView's viewWithTag to get the view with the specified tag.
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html
This is how I do it:
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:[textField convertPoint:textField.frame.origin toView:self.tableView]];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
I prefer this approach because it doesn't rely on tags or maintaining a reference to the container view from the UITextField, or traversing the view hierarchy. All those approaches are brittle for one reason or another.
Tags approach: You need to set the tag in tableView:cellForRowAtIndexPath: and if you have multiple sections, you need to encode the section.
Adding a property to UITextField: This either requires a UITextField category and associated objects, or subclassing UITextField. Both work, but are overkill.
Traversing the view hierarchy is brittle because it depends on implementation details that could change at any time.

UICollectionViewCells and Buttons

I've been trying to get my UICollectionView to respond differently to single and double taps but all the answers I have found seem to suggest this is not really feasible because the single taps get recognised first. It works on really slow taps, but anything faster always initiates the default gesture recogniser (if anybody has got this to work I would love to know)...
So anyway, I have now resorted to putting buttons in my UICollectionViewCell (which has it's own class and NIB file).
The question is this:
What is considered the best way to use the button in the UIViewController of the collectionView?
I currently have a protocol in the header of my subclass of UICollectionViewCell and have declared my viewController as the delegate and implemented the required protocol functions.
In collectionView:cellForItemAtIndexPath: I set the VC as the delegate of the cell.
It all works but it seems a bit long-winded, and maybe not a great way of doing this.
The other way I was thinking of was instead of using delegates to simply call addTarget:Action: on the property of the UICollectionViewCell in collectionView:cellForItemAtIndexPath:.
This seems simpler but the delegate pattern looks to me like the better fit.
Any and all advice on which would be better, why, and any more appropriate alternatives welcomed!
Thanks.
You're doing the right think using the delegation pattern. The ultimate responsible object for any action of your views is the viewController who's displaying those views. Therefore, using it as the delegate for you cell's protocol is just right.
create a custom subview of UICollectionViewCell and place your button in the initWithFrame method. Declare the button to be public so you can use it later in your uicollectionviewcontroller or uicollectionview if creating programmatically.

Why I'm getting gesture recognizers cannot be used on prototype objects?

I'm getting the above error from storyboard when I dropped a UITapGestureRecognizer inside a UIView which is inside a UITableViewCell in my scene.
Any idea why I'm getting this error ?
I'm not sure why the restriction is in place but I know why you are getting it the error.
When you design a UITableViewCell in StoryBoard you are only designing a prototype object. i.e. the object may never actually exist. It only gets ACTUALLY created in tableView:cellForRowAtIndexPath:
What might be a better approach is to create the gestureRecognizer when you configure the cell in code. This way you won't have this restriction.
I'd also possibly look at whether you actually need it? If it is just for a single tap with one finger then you may be better off coding the touchesEnded or just using a UIButton instead.
Found the reason myself. storyboard only allows that when we have a UITableViewController or it's subclass and the tableview content should be 'static cells' instead of default 'Dynamic Prototypes'. In that configures I can add a gesture recognizer inside the cell subview.
But that is a limitation and will not work in my case as I have a very customized view controller subclass instead of table view controller subclass. Need to find other way around it seems :(

How to notice if a UITableViewCell has left the visible area?

I'm stuck with the problem that I want to know in my UITableView if a specific UITableViewCell, let's say the first, is still visible or already off the visible area.
I would also be ok to know if the cell of interest is now beeing reused at an other indexPath of the table.
One of my - later and frustrated approaches - was to have a thread that knows the first cell object and frequently pings it to check if a value I did set in the cell changed. Obviously a not so good solution.
Andy ideas how to do this right?
Remember that UITableView is UIScrollView subclass and its delegate also confirms to UIScrollViewDelegate protocol as well.
So in your table delegate you can implement scrollViewDidScroll: method and check contentOffset - if it's more then first cell height then first cell is not visible. You can also get the array off all currently visible cells using -visibleCells method, but I think knowing contentOffset should be enough.

Resources