Embed 2 Dynamic UITableViews - ios

I have two UITableView's embedded into a UIViewController. Both are dynamic and retrieve the different data. The issue is that the indexPath is used in both tables when using - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath.
Is there a work-around here? I am referencing my entities like so:
//tableView2 has a cell named differently
static NSString *CellIdentifier = #"Cell";
static NSString *CellIdentifier2 = #"Cell2";
//reference the cells to the right tables
UITableViewCell *cell = [self.tableView1 dequeueReusableCellWithIdentifier: CellIdentifier forIndexPath:indexPath];
UITableViewCell *cell2 = [self.tableView2 dequeueReusableCellWithIdentifier: CellIdentifier2 forIndexPath:indexPath];
//create access to details the cell will display from the core date
entity1 * e1 = [self.fetchedResultsController objectAtIndexPath:indexPath];
//this is the issue
//entity2 * e2 = [self.fetchedResultsController2 objectAtIndexPath:indexPath];
The issue as mentioned is the indexPath. If I try to run the app with both entities equating to their respective fetchedResults it causes an error due to the indexPath being reused. If I create another indexPath it causes this error (understandably so):
'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.'
My question is, how do I reuse or create a separate reference to the NSIndexPath inside the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method, or is there a workaround?
I have already attempted using if/if else statements inside the method but this displays the same number of cells in both tables; if table1 has 10 rows there will be 10 rows in table2 regardless of content.
The below code is possibly incorrect, I am not experienced enough implementing two table views to know, but it's not the main issue:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if ([self fetchedResultsController]){
return [[self.fetchedResultsController sections] count];
}
if ([self fetchedResultsController2]) {
return [[self.fetchedResultsController2 sections] count];
}
else{
return 0;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self fetchedResultsController]){
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
if ([self fetchedResultsController2]){
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController2 sections]objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
else{
return 0;
}
}

First of all you don't have to create two sections.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
Then you have to set your Rows according to your tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.tableView1){
//Return the count you want inside self.tableView1
}
else if (tableView == self.tableView2){
//Return the count you want inside self.tableView2
}
else{
return 0;
}
}
Finally inside your cellForRowAtIndexPath set your table Values according to your TableView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.tableView1){
static NSString *CellIdentifier = #"Cell";
//reference the cells to the right tables
UITableViewCell *cell = [self.tableView1 dequeueReusableCellWithIdentifier: CellIdentifier forIndexPath:indexPath];
}
else if (tableView == self.tableView2){
static NSString *CellIdentifier2 = #"Cell2";
UITableViewCell *cell2 = [self.tableView2 dequeueReusableCellWithIdentifier: CellIdentifier2 forIndexPath:indexPath];
}
else{
return 0;
}
}

you need to set tags for tableviews. and in cellforRowAt IndexPath
if(tabaleView.tag==100)
{
UITableViewCell *cell = [self.tableView1 dequeueReusableCellWithIdentifier: CellIdentifier forIndexPath:indexPath];
}
else
{
UITableViewCell *cell2 = [self.tableView2 dequeueReusableCellWithIdentifier: CellIdentifier2 forIndexPath:indexPath];
}

Related

In UITableView,cellForRowAtIndexPath ignore the first few rows

I've used sqlite in my project and I get ten elements in _mChats (array) successfully. The numberOfRowsInSection method returns 10 but cellForRowAtIndexPath ignores the first few rows and in simulator other elements all display on the same cell,why?
And if I use sections instead of rows to display data,everything becomes normal.
This is my code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_mChats count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
VChat *cell = [VChat vChatWithTableView:tableView];
cell.mChat = _mChats[indexPath.section];
return cell;
}
I think its because of this
cell.mChat = _mChats[indexPath.section];
Try this instead
cell.mChat = _mChats[indexPath.row];
This is because Indexpath is a property that has two values inside it,
Eg. IndexPath [section,row] meaning indexpath of something is section number 1, row number 5.
Hope this helps you understand.
This is how your cellForRowAtIndexPath should look like:
- (UITableViewCell *)tableView:(UITableView *)iTableView cellForRowAtIndexPath:(NSIndexPath *)iIndexPath {
NSString *cellIdentifier = #"myCell";
UITableViewCell *cell = (UITableViewCell *)[iTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
cell.mChat = _mChats[indexPath.row];
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)iTableView cellForRowAtIndexPath:(NSIndexPath *)iIndexPath
{
VChat *cell = (VChat *)[tableViewdequeueReusableCellWithIdentifier:#"CellIdentifier"];
NSArray *nib = [[NSBundle mainBundle]loadNibNamed:#"VChat" owner:self options:nil];
if (cell==nil)
{
cell = nib[0];
}
cell.mChat = _mChats[indexPath.row];
return cell;
}
The three delegate method must be implement you have wrote have something wrong. As #Abhinav said the method return cell have some thing wrong.
As the code you showed will create a new cell when a new cell present in the screen. I think the first few rows just because the cell has't be reused.
There is another thing I want to say, if you are using storyboard to build the tableview this method should seems like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// The identifier in storyboard you setted.
static NSString *cellName = #"theCell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:cellName];
if (dataSource_[indexPath.row]) {
// This method will bind data to view
[cell fillDataWithDict:dataSource_[indexPath.row]];
}
return cell;
}

iOS UITableView contents not visible

In a VC I have 2 tableViews - 1 main and other is added in a drop down menu. From drop down menu TableView "ddTableView", I have added 5 cells in Storyboard itself as prototype cells. Each cell contains an image and a Label. Have also set identifier for each cell. Have also set Accessory Type as "Disclosure Indicator" for each cell of ddTableView.
DataSource and Delegate for mainTV is set to the VC and delegate for ddTableView is set the VC. As the rows are added within the storyboard, I didn't set any datasource for ddTableView in my VC. I managed my delegate methods like this :-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == ddTableView) {
// RETURNS NIL ???
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"CELL Identifier = %#", cell.reuseIdentifier);
return cell;
} else {
}
}
-(void )tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == ddTableView) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog (#" CELL Clicked of - %#", cell.reuseIdentifier);
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == ddTableView)
return 44;
else
return 60;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == ddTableView)
return 5;
else
return [chatMsgsArr count];
}
It does call respective delegate method. For cellForRowAtIndexPath it returns cell as nil. Why so ? And on execution, I don't see any contents of the table view - table is blank. I changed the bg color of image and text color also, but yet nothing is seen on execution.
Why so ? Where I may be going wrong ?
You have to allocate the cell, the first time cellForRowAtIndexPath is called. If the cell is not allocated it would return nil as you are getting right now.
What you need to do is allocate the cell only once, the first time you enter cellForRowAtIndexPath. After that you can reuse it as you have done.
If you are planning to use the default tableViewCell your method should look as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"your_cell_identifier_name";
if (cell == nil)
{
UITableViewCell *cell = [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
else
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
}
//write the code to populate your cell with data here
//return the cell object
return cell;
}
Hope this helps! :)
- (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] ;
}
if (tableView == ddTableView) {
NSLog(#"CELL Identifier = %d", indexpath.row);
} else {
NSLog(#"CELL Identifier = %#", [chatMsgsArr objectAtIndex:indexPath.row]);
}
return cell;
}

Expandable rows in UITableView is set to be opened

I have managed to make the TableView expandable. The problem is that when I start the app, it's always opened. I want it to be closed, and to be opened just when I hit the row.
What am I missing here? How can I set it to be open at start?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!indexPath.row)
{
// first row
cell.textLabel.text = #"Expandable"; // only top row showing
}
else
{
cell.textLabel.text = #"Some Detail";
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
{
return YES;
}
You first create a regular table with some array of booleans that holds the state of each row (open/close).
Then, when you hit a first row in a section, I reload the table with new rows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//subject hitted
if (indexPath.row == 0)
{
// set relevant boolean here ,also , reload the table again with the new rows
collapsedRows[indexPath.section]= ! collapsedRows[indexPath.section];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]withRowAnimation:UITableViewRowAnimationFade];
}
//sub subject hitted
else
{
}
}

UITableView Cells With DIfferent Format & Behavior in Same Table Section

I have a UITableView with one section. All of the cells in that one section have cells that are derived from a subclass of UITableViewCell called PLContactCell.
What I'd like to do is, for the very last row of the table only, not use a PLContactCell. I just want to use a normal UITableViewCell that I can format however I would like. I'd also like to be able to have this cell NOT respond to being tapped.
My initial cellForRowAtIndexPath method is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PLContactCell *cell = [tableView dequeueReusableCellWithIdentifier:[PLContactCell reuseIdentifier]];
if (!cell) {
cell = [PLContactCell reusableCell];
cell.delegate = self;
}
id modelObject = [[sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
if ([modelObject isKindOfClass:[NSString class]]) {
[cell configureWithString:modelObject];
} else {
[cell configureWithUser:modelObject];
}
return cell;
}
EDIT
So I tried created a UITableView cell in the XIB file and added the reuse identifier of "newCell" to it. Then I added this code:
if (indexPath.row == [[sections objectAtIndex:indexPath.section] count] - 1) {
NSString *CellIdentifier = #"newCell";
noFormatCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
This doesn't do anything. My question is, how do I access the last row of the section and how do I make it so that that cell it is not a PLContactCell but a UITableView Cell.
If it's always at the end, you might consider using the footer view of the UITableView. You can then keep some extra logic out of your UITableViewDataSource.
If it HAS to be as a cell, you'd have to add an extra row count on your last section, then do an if statement check to watch out for it in your -tableView:cellForRowAtIndexPath: implementation. I would strongly urge you try the footer approach, as it's cleaner and way easier to figure out what you were doing a few months/years from now.
Here's some code. Note you'd need to make another section if you are using grouped style in the UITableView.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == sections.count - 1) //Looking for last section
{
return [sections objectAtIndex:section].count + 1; //Add one to the last section
}
return [sections objectAtIndex:section].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger row = indexPath.row;
if ((sections.count == indexPath.section) && [sections objectAtIndex:indexPath.section].count == indexPath.row)
{
//Here you would create and return your UITableViewCell
}
PLContactCell *cell = [tableView dequeueReusableCellWithIdentifier:[PLContactCell reuseIdentifier]];
if (!cell) {
cell = [PLContactCell reusableCell];
cell.delegate = self;
}
id modelObject = [[sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
if ([modelObject isKindOfClass:[NSString class]]) {
[cell configureWithString:modelObject];
} else {
[cell configureWithUser:modelObject];
}
return cell;
}

i want to number my rows in a UITableView

im using core data i have an entity called questions whenever i add my question to my table i want them to display the number of the question (kind of like auto increment thing)
can anyone pls help me out
thanks
here is my code if its relevant
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.questionArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
// Configure the cell...
questionObject = [self.questionArray objectAtIndex:indexPath.row];
cell.textLabel.text = questionObject.questionDescription;
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (nil == cell) {
cell = ...; //create a cell instance if it wasn't found in reusable cache
}
// Configure the cell...
questionObject = [self.questionArray objectAtIndex:indexPath.row];
NSString *cellText = [NSString stringWithFormat:#"%d. %#", indexPath.row+1, questionObject.questionDescription];
cell.textLabel.text = cellText;
return cell;
}

Resources