I have setup a uitableview with custom cells.
I would like these into sections with a title. Looking at the below photo I am looking for the following layout:
Section - My Profile
Custom cell - wwwwwwwwwwwwww...
Section - Application
Custom cell - Games
Custom cell - Share
Custom cell - Rate
Custom cell - Settings
Custom cell - Help
Custom cell - Log out
I can see how to add a section and control the rows in a section, but this duplicates the cells into multiple sections, I am not sure how to have one section with one row and another section with 6 rows. I also want to style these sections to show, slightly like the Facebook menu style.
Should I create custom cells for the actual sections instead and have no action on the section (cell) selection?
Here is the code for the UITableView
static NSString *CellIdentifier = #"Cell";
LeftMenuTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"LeftMenuTableViewCell" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]]) {
cell = (LeftMenuTableViewCell*)view;
}
}
}
You could define number of sections and rows in it as following:
- (UIView *) tableview:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView view;
if(section == 0) {
// Initialise view for section 1
} else {
// Initialise view for section 2
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return ((section == 0) ? 1 : 6);
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return appropriate cell(s) based on section
if(indexPath.section == 0)
{
// Return 1 cell
}
else if(indexPath.section == 1)
{
switch(indexPath.row) {
case 0: // Initialize cell 1
break;
case 1: // Initialize cell 2
break;
...
}
}
return cell;
}
Related
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;
}
I'm working with Xcode 6.1.1, and I have a table view controller with static cells having 4 sections.
Section 0: contains two rows, each with 2 labels
Section 1: contains 7 image views
Section 2: contains 1 row with 1 label
Section 3: contains a variable number or rows each containing 2 image
views
I want to load all cells in the table view controller with data.
I gave each different row a reuse identifier (5 reuse identifiers in total), and I also created a class for each of the different kind of cells (5 classes)
I created outlets in the classes, and linked them in the storyboard each to its label/image view.
However I don't know how to proceed next.
If I implement the table view data source functions, I'm getting the correct number of cells, however they are all blank.
Here's how I'm creating the cells:
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
if (indexPath.section == 0 && indexPath.row == 0) {
static NSString *CellIdentifier = #"MyCell1";
MyTableViewCell1 *cell = (MyTableViewCell1*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MyTableViewCell1 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
} else {
//create other cells here
}
cell.label1.text=#"testing 123";
return cell;
}
However, I'm always getting cells with default style (my labels or image views are not appearing)
What am I missing?? What code should I write in the custom table view cell classes?
EDIT: After gavin's suggestion, I modified the delegate function to use the dequeueReusableCellWithIdentifier:forIndexPath
I also added: [self.tableView registerClass:[MyTableViewCell1 class] forCellReuseIdentifier:#"MyCell1"] to my viewdidload method.
Here's my final code:
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[MyTableViewCell1 class] forCellReuseIdentifier:#"MyCell1"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 3 ) {
return 1;
} else {
return [super tableView:tableView numberOfRowsInSection:section];
}
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
if (indexPath.section == 3) {
// make dynamic row's cell
static NSString *CellIdentifier = #"MyCell1";
MyTableViewCell1 *cell = (MyTableViewCell1*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell configureCellWithValues:#"17" andV2:#"13"];
return cell;
} else {
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 3) {
MyTableViewCell1 *c = (MyTableViewCell1 *) cell;
NSLog(#"willdisplay cell with values %#, %#",c.i1, c.i2);
[c.image1 setImage:[UIImage imageNamed:#"2"]];
}
}
And here's my custom cell's class:
#implementation MyTableViewCell1
- (void)awakeFromNib {
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void) configureCellWithValues: (NSString*) v1 andV2:(NSString*) v2 {
self.i1=v1;
self.i2=v2;
self.image1.image = [UIImage imageNamed:v1];
self.image2.image = [UIImage imageNamed:v2];
}
#end
The cells in section 3 are still not showing the images (not even the imageviews)
Look like you're using the old method of tableView reusable cell dequeueing - the new function accepts an indexPath as well as the cell identifier; it also now guarantees to return a cell (so no need for a nil check).
Here's your delegate function cleaned up:
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
if (indexPath.section == 0 && indexPath.row == 0) {
static NSString *CellIdentifier = #"MyCell1";
MyTableViewCell1 *cell = (MyTableViewCell1*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
} else {
//create other cells here
}
cell.label1.text=#"testing 123";
return cell;
}
Another tip would be to encapsulate your setting of the label values into each individual cell subclass, e.g. add a method called configure to MyTableViewCell1 that sets the label values to what you want displayed.
It seems that we can't generate custom static cells and try to access their outlets and change them (because their static) please correct me if i'm wrong because I couldn't access them at all.
I've solved my Problem by changing the TableView Type to Dynamic Cells, i didn't put any prototype cells in the tableview and I have created 3 different Cell Classes (with their nibs)
I have registered the nib files with the tableview by adding this to the viewdidload method:
[self.tableView registerNib:[UINib nibWithNibName:#"MyCellType1" bundle:nil] forCellReuseIdentifier:#"CellType1"];
[self.tableView registerNib:[UINib nibWithNibName:#"MyCellType2" bundle:nil] forCellReuseIdentifier:#"CellType2"];
[self.tableView registerNib:[UINib nibWithNibName:#"MyCellType3" bundle:nil] forCellReuseIdentifier:#"CellType3"];
then i fully customized my tableview methods:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
switch (section) {
case 0:
return 2;
break;
case 1:
return 1;
case 2:
return [self.myarray count];
default:
break;
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case 0: {
MyCellType1 *cell = (MyCellType1 *) [tableView dequeueReusableCellWithIdentifier:#"CellType1" forIndexPath:indexPath];
//this section always has 2 rows
if (indexPath.row==0) {
cell.lblTitle.text = #"ID";
cell.lblValue.text = [NSString stringWithFormat:#"%i",1277];
} else {
cell.lblTitle.text = #"Date";
cell.lblValue.text = #"02/03/2015";
}
return cell;
}
break;
case 1: {
MyCellType2 *cell = (MyCellType2 *)[tableView dequeueReusableCellWithIdentifier:#"CellType2" forIndexPath:indexPath];
cell.image1.image = [UIImage imageNamed:#"3"];
cell.image2.image = [UIImage imageNamed:#"4"];
return cell;
}
case 2: {
MyCellType3 *cell = (MyCellType3 *)[tableView dequeueReusableCellWithIdentifier:#"CellType3" forIndexPath:indexPath];
cell.lblName.text = #"New Row";
return cell;
}
default:
break;
}
return nil;
}
I'm basically making a settings view on my app and I'm using a static table for it. So I divided the table into 3 sections each with one cell. Not programmatically I can easily label each cell and it works but programmatically I'm not able to initialize each cell. I can only initialize the first cell that gets repeated across the 3 sections. I would like a way to initialize a cell for each section but I can't find a method or a way to do that. My tableview also has reuseIdentifiers but it doesn't seem like the UITableViewController recognizes it.
This is what I have done so far.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"EditProfile";
//UITableViewCell *cell = nil; //[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// More initializations if needed.
}
//Observations *currentList = [self.teacherNames objectAtIndex:indexPath.row];
cell.textLabel.text = #"Hey";
//return cell;
return cell;
}
But what I want is the cell in the first section to be labeled: Edit Profile, the second one: Invite and the third:Logout
You have to make a condition for how to handle each different section within the table view.
if (indexPath.section == 0) {
cell.textLabel.text = #"Edit Profile";
}else if (indexPath.section == 1) {
cell.textLabel.text = #"Invite";
}else if (indexPath.section == 2) {
cell.textLabel.text = #"Log out";
}......
Check out the tableView delegate methods:
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
(IF you're wanting to label the section headers and not the cells in the sections themselves)
I'm looking for the best possible solution for a complex UITableView. What I want : I have an arbitrary number of sections. In this section is just one static cell and then should come any number of dynamic cells.
My Data are stored in some NSMutableArray and i tried somethink like this:
Combine static and prototype content in a table view
But i dont know how to handle it with my kind of problem.
So can somebody give me a hint or a best practice?
UPDATE: 1
http://jsfiddle.net/konstheinrich188/HKkA8/ Fiddle shows how my data looks and what im trying todo
This pic shows how i want to code my tableview...
When you are using the term "static", are you really talking about a "uitableview static cell", or rather "cell with static content"?
If the former; why do you need that?
If the latter; how about testing in each section whether this is the first cell in the section, and then presenting static content? For all other cells, display dynamic content:
if (indexPath.row == 0) {
// First row in section. Display static content
...
} else {
// Display dynamic content
...
}
For what purpose do you need the static cells?
So after a while and some testing and listen to your ideas and technicals i solved my problem!
Here is a little code :
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [mappedSprints count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
UISprint*s = [mappedSprints objectAtIndex:section];
return s._name;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
UISprint* s = [mappedSprints objectAtIndex:section];
return [s.internalUserStorey count] + [s.externalUserStorey count] + 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
return 130;
}
return 80;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:#"Cell%d%d", indexPath.row, indexPath.section]];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:#"Cell%d%d", indexPath.row, indexPath.section]];
}
UISprint*s = [mappedSprints objectAtIndex:indexPath.section];
if (indexPath.row == 0) {
//Here is my first cell
//cell.textLabel.text =s._name;
}
else if(indexPath.row >= 0 && indexPath.row<=[s.internalUserStorey count]){
//here are the cells for SubItem
}
else if(indexPath.row >= [s.internalUserStorey count]){
//here are the cells for SubItem 2
}
return cell;
So thanks to all !!
Best Konstantin
You can take one NSMuatableArray and add references on that i.e.
NSMuatableArray *arr=[NSMuatableArray alloc]init];
//section no 1
[arr addObject:#"2"];
//section no 2
[arr addObject:#"1"];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
switch(arr objectAtIndex[indexPath.row])
{
}
}
you can use this way by using references you want set cells.
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;
}