Displaying different sets of data in the same UITableView based on conditions - ios

I have 3 lists to be displayed in a UITableView based on some conditions.
I am using a custom tableview cell to display it. So if the data is of the first set, I have to display total of 5 labels in a row; if it is of second set then I have to display 2 labels and for the 3rd set 1 label, and its alignment will be different.
By using a storyboard, can I display this kind of data?

You can use TableView sections to differentiate different data sets. You can switch off of the section to create the custom information for each dataset.
#pragma mark - UITableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection (NSInteger)section {
NSInteger rows;
switch (section) {
case 0:
rows = firstSet.count;
break;
case 2:
rows = secondSet.count;
break;
default:
rows = 0;
break;
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] init];
switch (indexPath.section) {
case 0:
//Custom cell for first section
cell = [self customFirstSectionCell];
break;
case 2:
//Custom cell for second section
break;
default:
rows = 0;
break;
}
return cell;
}

Related

How to check the selected row in UITableView is of which group/section

Is it possible to get the section count for the respective selected row in a UITableView
yes you can check for section with
indexPath.section
If you have NSIndexPath you can get row by
indexPath.row
or section by
indexPath.section
Try the following sample code:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 5;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger rows = 0;
switch (section) {
case 0:
rows = 7;
break;
case 1:
rows = 21;
break;
case 2:
rows = 3;
break;
case 3:
rows = 1;
break;
case 4:
rows = 5;
break;
default:
break;
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CELL" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = [NSString stringWithFormat:#"section : %ld & rows : %ld",(long)indexPath.section,(long)indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//This will print which row of which section is clicked
NSLog(#"section : %ld & rows : %ld",(long)indexPath.section,(long)indexPath.row);
}
which is right !
NSArray <NSIndexPath *>*rows = [tableView indexPathsForSelectedRows];
I solved what i was looking for. I wanted to get all the section number for the respective selected rows in it, on the button click.
I used
NSArray *paths = [self.tableView indexPathsForSelectedRows];

Using a static UITableViewController to create two sections with the first section having a non-static number of cells

I have a UITableViewController that I'm building up in my application. This UITableViewController (SelectedLanguages) is called from another UITableViewController (ChooseLanguage) where there is a static list of languages for the user to select.
In the SelectedLanguages UITableViewController, I want to achieve the following:
2 Sections
The first section will have between 1 and 5 cells
The second section will always have 12 cells.
The number of cells in the first section is entirely dependent on which language the user chooses in the ChooseLanguage UITableViewController. For example, clicking on English will mean the first section in the SelectedLanguage UITableViewController will have 5 cells, but choosing French in the ChooseLanguage UITableViewController will mean the first section in the SelectedLanguage will only have 1 cell.
As mentioned, the second section will always have 12 cells in the SelectedLanguage.
I have designed this UITableViewController in Interface Builder. What I've seen is that only if the the Content is specified as Static Cells can you have multiple "sections".
Even if you set the Content to Dynamic and Grouped, I can't seem to find a way to determine sections other than in code.
The reason I'm defining this in Interface Builder is because section 1 and section 2 will need to have a very customised layout of the size of the cells, as well as the labels that go into each cell.
The content of the first section is not dynamic; it is static because while building this application, I'll know exactly how many cells there should be in the first section for each language, so in my head, it is correct to use a Static cell.
My question is, how can I achieve setting the number of cells in the top section, in code?
In the prepareForSegue of the ChooseLanguage, I could check the called cell title and then perform some action in the SelectedTransactions. The action to perform here is what I'm confused about.
I know there's the method - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section in the UITableView Data Source, but I'm not sure how and what to do with this with my particular situation.
Any guidance would be really appreciated.
My easiest answer for your question is below
in .m
import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *arraysection1;
NSMutableArray *arraysection2;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
arraySection1 = [[NSMutableArray alloc]initWithObjects:#"One",#"Two",#"Three",#"Four",#"Five",nil];
arraySection2 = [[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5",nil];
}
#UITableView Delegate Methods
#UITableView DataSource Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//If you have 2 sections,
return 2;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//set row of two sections with condition
if(section==0)
{
return arraySection1.count;
}
else
{
return arraySection2.count;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *strCellIdentifier = #"CellIndentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:strCellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strCellIdentifier];
}
if(indexPath.section==0)
{
cell.textLabel.text = [NSString stringWithFormat:#"%#",[arraySection1 objectAtIndex:indexPath.row]];
NSLog(#"The textLabel is-%#",cell.textLabel.text);
}
else
{
cell.textLabel.text = [NSString stringWithFormat:#"%#",[arraySection2 objectAtIndex:indexPath.row]];
NSLog(#"The textLabel is-%#",cell.textLabel.text);
}
return cell;
}
#UITableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section==0)
{
if(indexPath.row==0)
{
//Do whatever you want here
}
else if(indexPath.row==1)
{
//Do whatever you want here
}
else if(indexPath.row==2)
{
//Do whatever you want here
}
else if(indexPath.row==3)
{
//Do whatever you want here
}
else
{
//Do whatever you want here
}
}
else
{
if(indexPath.row==0)
{
//Do whatever you want here
}
else if(indexPath.row==1)
{
//Do whatever you want here
}
else if(indexPath.row==2)
{
//Do whatever you want here
}
else if(indexPath.row==3)
{
//Do whatever you want here
}
else
{
//Do whatever you want here
}
}
}
From what you are describing it sounds like your tableView should be dynamic.
You will have to handle this programmatically, forget about interface builder
Here is what you need:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;//2 Sections
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
switch (section) {
case 0:
//The first section will have between 1 and 5 cells
//Put the logic to return the correct number of cells
return 5;
break;
case 1:
//The second section will always have 12 cells.
return 12;
break;
default:
break;
}
return 0;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
switch (indexPath.section) {
case 0:
[[cell textLabel] setText:#"same title section 1"];
break;
case 1:
[[cell textLabel] setText:#"same title section 2"];
break;
default:
break;
}
return cell;
}

UITableView - Set height of cell to fit text

I have a UITableView and I want the first cell of this UITableView to be a description of what is being showed so this will take up a few lines and then the rest of the cells are the hours of operation. I have the table view set up like this. And I am wondering how to set the first cell so that the height of it matches the amount of room need to fit the text:
- (void)viewDidLoad {
[super viewDidLoad];
array = #[#{#"days":#"sdalkfjsadklfjlak8 aslfkjsakljf sdakljfsalkdjfs dfkljsdakfjkjlfjsakkjja"},
#{#"days":#"Mon-Fri", #"time":#"9-10"},
#{#"days":#"Sat", #"time":#"10-3", #"tag":#"0"},
#{#"days":#"Sun", #"time":#"3-3"} ];
}
- (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 diningHallTimes.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.row) {
case 0:
return 60;
break;
default:
return 40;
break;
}
}
So how would the best way to set it so that the text always fits in the height of the first cell?
Thanks for the help

Hiding UITableView sections with delegate methods not drawing headers correctly afterwards

I have two sections in my UITableView populated by predicate filtering of a single array as their datasource. When the predicate filtered arrays have items in them, the headers are drawn (colored) correctly and are at the correct positions. The colors are set in willDisplayHeaderView.
Note, this is NOT a UITableViewController, but a UITableView that is part of a more complex view.*
New items can be added to the table with an add (+) button.
When I delete items from a section until it has 0 items, the header disappears correctly.
When I add a new item to one of these empty (and now invisible) sections, the header is drawn and named correctly, but it's not colored correctly and appears slightly overlapping the section above it (or in the case of the first/0th section, it appears under the table top so you can't see half the text).
It's almost like willDisplayHeaderView isn't getting called when a section not previously there is now added because it's datasource now has data.
Here are my methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return kSectionCount;
}
and
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
switch (section) {
case kIncompleteActivitiesSection:
return [[_activitiesArray filteredArrayUsingPredicate:_predIncomplete] count];
case kCompleteActivitiesSection:
return [[_activitiesArray filteredArrayUsingPredicate:_predComplete] count];
default:
return 0;
}
}
and
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// return the section names
switch (section) {
case kIncompleteActivitiesSection:
if ([[_activitiesArray filteredArrayUsingPredicate:_predIncomplete] count] > 0) {
return #"Upcoming Activities";
} else {
return nil;
}
case kCompleteActivitiesSection:
if ([[_activitiesArray filteredArrayUsingPredicate:_predComplete] count] > 0) {
return #"Completed Activities";
} else {
return nil;
}
default:
return 0;
}
}
and
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {
// set header text Color
UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;
[header.textLabel setTextColor:[UIColor whiteColor]];
// set header background color
header.backgroundView = [UIView new];
header.backgroundView.backgroundColor = _colorSchemeColor;
header.backgroundView.alpha = 1.0;
}
When you change your _activitiesArray you have to reload the section(s) that are affected. The section headers are not updated automatically, in my experience.
[self.tableView beginUpdates];
//Update your data model here
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
You can substitute whichever row animation style you prefer.

How to duplicate and retrieve data from an UIView with many UITextviews in it

I am trying to understand the best approach to create something like this:
I would like to know how to clone the UIViews and retrieving each data from UITextViews above.
I am using storyboard here, is it can be done by adding container view?
Thanks!
Update
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView registerClass: [TitleCell class] forCellReuseIdentifier:#"Title"];
TitleCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Title" forIndexPath:indexPath];
switch (indexPath.row) {
case 0:
cell.leftLabel.text = #"Title";
//cell.labelRight.text = self.theData[indexPath.section][#"Title"];
break;
case 1:
cell.leftLabel.text = #"FirstName";
//cell.labelRight.text = self.theData[indexPath.section][#"FirstName"];
break;
case 2:
cell.leftLabel.text = #"LastName";
//cell.labelRight.text = self.theData[indexPath.section][#"LastName"];
break;
default:
break;
}
return cell;
}
It's not returning error now, but the weird thing is that it didn't show up the leftLabel text.
Yes I am using storyboard.
The best way to implement that is with a UITableView, you don't need to "clone" anything. The image you posted looks like a table view with sections, with each section having 5 rows. The cells each have two labels, one on the left with fixed text, and one on the right with data which you would populate from a data source. Here's an example that has 3 rows per section. The data source is an array of dictionaries with keys, Title, FirstName, and LastName.
self.theData = #[#{#"Title":#"Mr",#"FirstName":#"Joe",#"LastName":#"Montana"},#{#"Title":#"Dr",#"FirstName":#"Julius",#"LastName":#"Irving"},#{#"Title":#"Mr",#"FirstName":#"Alex",#"LastName":#"Smith"}];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RDCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
switch (indexPath.row) {
case 0:
cell.labelLeft.text = #"Title";
cell.labelRight.text = self.theData[indexPath.section][#"Title"];
break;
case 1:
cell.labelLeft.text = #"FirstName";
cell.labelRight.text = self.theData[indexPath.section][#"FirstName"];
break;
case 2:
cell.labelLeft.text = #"LastName";
cell.labelRight.text = self.theData[indexPath.section][#"LastName"];
break;
default:
break;
}
return cell;
}

Resources