Detect touch on Cell of UITableView contained in UICollectionView - ios

I am creating a Chinese learning app, with a section for correctly pronouncing certain sounds. To organise these sounds into a table, I have created a UICollectionView, where each UICollectionViewCell contains a UITableView.
Each UICollectionViewCell acts as a column, and contains a UITableView.
Each UITableViewCell acts as a row in each column.
This results in the following appearance.
However, although I can easily detect taps on each UICollectionViewCell using collectionView:didSelectItemAtIndexPath: , I am unable to detect any touches at all on the UITableViewCells within.
Whether I convert the view in the Cell to be a button, or whether I as a UITapGestureRecognizer, or whether I use the function tableView:didSelectItemAtIndexPath, no touches at all are detected in the UITableView.
How can I allow my code to correctly detect these touches on the UITableViewCells within the UICollectionView?
Thanks!
Update 1:
Here is the #interfact of the Column .h file (UICollectionViewCell)
#interface PronounciationColumn : UICollectionViewCell <UITableViewDelegate, UITableViewDataSource>
In the .m of the UICollectionViewCell, the delegate and dataSource of the tableView is set to self.
Update 2:
Another user had a really neat idea of setting the delegate of the tableView to it's own collectionViewCell using the following code:
- (PronounciationColumn *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
PronounciationColumn *column;
NSString *columnIdentifier = [self getIdentifier:collectionView];
if (column == nil) {
column = (PronounciationColumn *)[collectionView dequeueReusableCellWithReuseIdentifier:columnIdentifier forIndexPath:indexPath];
column.arrayOfFinals = [[self getArrayOfPinyins:collectionView] objectAtIndex:indexPath.item];
}
column.tableOfFinals.delegate = column;
column.tableOfFinals.dataSource = column;
return column;
}
The tableView continues to be populated correctly, however, the touches are still not detected on the cells, as tableView:didSelectRowAtIndexPath: is still not called.

Related

Get `UITableViewCell` indexPath using `UIScrollView`

I have a UITableViewCell which contains a UICollectionView. The UITableViewCell also contains a UIPageControl. I want to change the dots as the UICollectionView is swiped. I am using
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
to get the current visible UICollectionViewCell. But my problem is that since the UICollectionView lies in UITableViewCell to fetch the reference to the collectionView I require the indexPAth of the current table view in which collection cell is being swiped. How can I do this?
I want to do this:
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
// Change the dots
CustomTableCell *tableCell = [self.currentTable cellForRowAtIndexPath:_tablecellIndex];
NSInteger currentIndex = tableCell.currentCollectionView.contentOffset.x / tableCell.currentCollectionView.frame.size.width;
tableCell.currentPageControl.currentPage = currentIndex;
}
But how do I get the _tablecellIndex?
I tried doing :
NSArray *indexes = [self.currentTable visibleCells];
_tablecellIndex = indexes[0];
But this is not always true as sometimes the table cells are displayed half and user is swiping second cell.
You need to ask the tableview itself, what indexpath a given cell has. You do that with this command :
[self.formTableView indexPathForCell:myCell];
The other problem in your case is that you are within the collection view on the cell, and not within the tableview itself. So theres a few ways to do that - one nice way is to set up a delegate on the cell that can access the tableview. Thats a bit involved, so heres an even simpler way (self in this case is the cell object):
UITableView *parentTableView = (UITableView*)self.superview;
NSIndexPath *cellIndexPath = [parentTableView indexPathForCell:self];
That should do the job.

Detect the last UITableViewCell of the current visible in UITableView

I would like to know if there is a way to detect if the current UITableViewCell is the last one in view then when the user pressed enter you will scroll the UITableView using this code
int cellHeight = 44;
[finishingTableView setContentOffset:CGPointMake(finishingTableView.contentOffset.x,finishingTableView.contentOffset.y + cellHeight) animated:YES];
I have a UITableView with custom UITableViewCells, each UItableViewCell has a UITextfield and I am programmatically selecting the UITableViewCell then making the cells textfield become first responder. I want to allow the user to hit enter all the way to the bottom of the UITableView but only start scrolling when the next UITableViewCell to select is out of view.
Use the indexPathsForVisibleRows method of UITableView.
NSArray *visibleRows = [self.tableView indexPathsForVisibleRows];
NSIndexPath *lastRow = [visibleRows lastObject];
Then compare that to the indexPath you have for the cell you are dealing with.

Cannot set properties on custom table view cell

I have a problem settings my view elements on a custom cell. The table cells appear in my tableView, but the properties do not set and thus only empty/blank cells appear.
The tableView is not a tableView controller, but only a tableView in a viewController.
I have the following files:
CustomCell.xib:
Here i use IB to build the custom cell by using a Table View Cell from object library with labels and images on. I set the Identifier as orderListCell. From this screen I ctrl+drag to create the outlets in customCell.h
CustomCell.h
Here I see all my IBOutlets as properties from above mentioned file
CustomCell.m
Here I leave as is
OrderListViewController.h
Here I import customCell.h and use protocols UITableViewDelegate, UITableViewDataSource
OrderListViewController.m
Here I set my tableView delegate and tableView dataSource to self. I also create an IBOutlet for my tableView from the Storyboard.
I use the following code to try and display my cells:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"orderListCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[CustomCell alloc] init];
}
cell.myLabel.text = #"aaaaaaaa"; //[[self.orders objectAtIndex:indexPath.row] objectForKey: #"tableNo"];
return cell;
}
I have simplified my code a bit to demonstrate that even setting the label to a simple string (#"aaaaaaaa") doesnt work. When I look at the objects in my debugger the cell does have all the properties from the IBOutlets and the cell does appear in my tableView, just the label.text = xxx does not seem to work.
I have looked at the following posts but either dont understand it properly or it does not work for me:
ios 7 customizing UITableViewCell's content view
Can't set properties in Custom UITableViewCell
Set label for a custom cell
Any help or advice would be greatly appreciated
cell = [[CustomCell alloc] init]; does not create your cell from the XIB, so none of the XIB content will be created.
Use registerNib:forCellReuseIdentifier: to register the XIB with the table view so that it will create your cell instances for you (you don't need to create instances yourself in cellForRowAtIndexPath).
If you don't want to do that, you can load your NIB explicitly with nibWithNibName:bundle: and instantiateWithOwner:options:, then get the cell instance from the list of returned views (which should only contain 1 item).

How to alter tableview cell text?

I have a UITableView that I want to alter some of the static cells after I do other processing. I have outlets set up for the cells that I want to modify, but when I look at them using NSLog, they show nil, which indicates to me that I don't have the correct cell. For instance, in the image below I want to add the start time to the label just like I did for Date (date was done when creating the cells for which I got the current date),
I tap on the disclosure indicator which takes me to another scene (this was created in Storyboard, using segues to get from one scene to another) where I get the two times I need. I then return to the main scene (shown) and try to alter the Start Time label, but nothing happens. A NSLog of the label prior to trying to alter it returns this:
oStartTimeCell.textLabel.text: (null)
I have read in one of the Apple docs that this textfield is read-only. If that is true in this case, is there a way I can reload the cells with the updated information? Or is there another way to do this?
You're using the wrong approach. You should not create a reference to a cell using an outlet. Once the cell moves out of the visible view, the outlet will either be null or contain garbage data. Even if (in your situation) the cell will never move out of view, I think it shows you're trying to use a UITableView in a way that was not meant to be.
Instead put the data you want to display in your cells in a dataSource, e.g. an array.
The tableView should use the dataSource to configure the values displayed in the textLabels of the cells. Once you want to update the text displayed in the cells, change the values in the dataSource and call reloadData on the tableView to force the tableView to call -tableView:cellForRowAtIndexPath: and related UITableViewDataSource methods.
Try to create an IBOutlet for each cell and connect it:
IBOutlet UITableViewCell *cell1;
IBOutlet UITableViewCell *cell2;
IBOutlet UITableViewCell *cell3;
And also change your method to:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(indexPath.row == 0) return cell1;
if(indexPath.row == 1) return cell2;
if(indexPath.row == 2) return cell3;
if (cell == nil) {
//create cell;
}
return cell;
}
Are you using a UILabel to display the text ? . If you are just create an outlet to the UIlabel and update it any method like cellForRwoAtIndexPath or didSelectRowAtIndexPath etc that is called after you tableView is loaded.
If you are not using a UILabel and just using cell.textLabel you could do something like
cell.textLabel.text = #"ChangedText" in cellForRowAtIndexPathMethod. Make sure you are editing the required cell by checking indexPath.row
Do [tableView reloadData] to call cellForRowAtIndexPath.

UITableView cells not drawing until the cell is at the top of the screen

I am building a table where each cell of the UITableView is a UIViewController. I have three different UIViewControllers I need to show in three rows of the table. I set the row of each cell to match the size of the UIViewController so each row is a different height.
When the app first starts, only the UIViewController in the first cell shows up. The contents of the next row doesn't show up until I scroll the table so that the top of that row is at the top of the screen. Likewise if I scroll down slightly so that a row is slightly off the bottom of the screen, when I scroll back up a little, the row contents are gone.
Here's the code I'm using. Note: The controllers to are created in the viewdidload method
What am I missing? Thanks
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
switch(indexPath.section)
{
case 0:
{
[cell.contentView addSubview:patientInformationController.view];
break;
}
case 1:
{
[cell.contentView addSubview:labsController.view];
break;
}
case 2:
{
[cell.contentView addSubview:planController.view];
break;
}
default:
break;
}
}
return cell;
}
UITableViewController is a huge, high-level construct for efficiently managing entire screens of data and UI objects. UITableViewCell is a tiny, efficient, highly-optimized view class designed to be drawn and updated as fast as possible.
Do not, ever ever ever, add a UIViewController's view to the contentView of a UITableViewCell. A few labels, an image, maybe a small control such as a UISwitch or UITextView.
If you haven't already, start reading here.
If you want to associate your view controllers (patientInformationController, labsController) with a particular row of the table view, the proper method is to just set the cell label for that row to a human-readable string, such as #"Patient Information", or #"Labs", and then, when the row is selected, use a UINavigationController to push the proper view controller.
UINavigationController manages a stack of UIViewControllers. A UIViewController manages a single coherent interface, usually comprised of a bunch of cooperating views. UITableViewController is a subclass of UIViewController which manages a single UITableView. UITableView is a class which specializes in the lightning-fast rendering and presentation of tabular data, organized into sections and rows according to a delegate and data source that you provide. One of the capabilities of UITableView is to inform its delegate in the event of the user selecting a row of the UITableView, allowing the delegate to present, via a UINavigationController, a new UIViewController for the presentation to the user of yet more detail and functionality.
Hope this helps. Start reading.

Resources