I have a single array of any count. I want to divide in different section as multiple of 7. I am unable to get this to work. Here is a sample of 2 elements.
- (void)viewDidLoad {
[super viewDidLoad];
array =[NSMutableArray arrayWithObjects:#"d",#"s",#"a",#"qq",#"dqd",#"dqq",#"qdqdf",#"dqdfqf", nil];
// Do any additional setup after loading the view from its nib.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return ceil(array.count / 2.0); // round up the floating point division
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger sections = [self numberOfSectionsInTableView:tableView];
if (section == sections - 1) {
NSInteger count = array.count & 2;
if (count == 0) {
count = 2;
}
return count;
} else {
return 2;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
Your question isn't clear but I think you want 7 rows in every section except the last section which would have just enough for the last remaining rows that don't fit in the rest of the sections.
Assuming this is correct you need to properly calculate the number of sections as follows:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return ceil(array.count / 7.0); // round up the floating point division
}
Now the number of rows in each section will be 7 except for the last section which could have 1 - 7.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger sections = [self numberOfSectionsInTableView:tableView];
if (section == sections - 1) {
NSInteger count = array.count % 7;
if (count == 0) {
count = 7;
}
return count;
} else {
return 7;
}
}
You also need to be able to convert an indexPath into an array index:
NSInteger index = indexPath.section * 7 + indexPath.row;
And you need to be able to convert an array index into an indexPath:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index % 7 inSection:index / 7];
Or, instead of all of this, you could setup your data structures to be an array of arrays. That actually makes your data better match how it will be used by the table.
Update for you revised question:
Your cellForRowAtIndexPath method needs to change:
//cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
to:
NSInteger index = indexPath.section * 7 + indexPath.row;
cell.textLabel.text = tableData[index];
just like I showed above.
So I'm not entirely on point with objective-C as it's been awhile.
But the easiest thing I'd think to do would be a for loop that iterates through the length of the array and at every 7th will divide the array.
Here's a bit of psuedocode.
for(int i =0; i<array.length<i=i+7)
{
//take the first index, take the 7th index.
//split the array from the first index to the 7th
//repeat for all remaining values.
}
I'm not sure if you wanted all the different sections that it could make from the 7 intervals, or only one. If you could clarify I might be able to answer this better.
Related
I have a UITableview with three custom(Xib) cells. I loaded each cell's in cellForRowAtIndexPath statically. Each cell contains add button to insert new row at next row. When i insert new row, it shows another Xib cell instead of expected cell and also new row adding in all sections.How to resolve it in Objective C?.
Note:
1) Cells loaded statically.
2) But inserting cell dynamically.
3) In numberOfRowsInSection method rows count given using an array(NSMutableArray) count.
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ if (indexPath.row==0)
{
CustomCellA *aCell = [tableView dequeueReusableCellWithIdentifier:#"ACell"];
return aCell;
} else if(indexPath.row==1)
{
CustomCellB *bCell = [tableView dequeueReusableCellWithIdentifier:#"BCell"];
return bCell;
}else
{
CustomCellC *cCell = [tableView dequeueReusableCellWithIdentifier:#"CCell"];
return cCell;
}
}
-(void)insertNewACell:(UIButton *)addButton atIndexPath:(NSIndexPath *)addBtnIndexPath
{
newArray = [[NSMutableArray alloc]init];
[newArray addObject:#"XXXX"];
[newArray addObject:#"YYYY"];
[newArray addObject:#"YYYY"];
[sectionRowItems addObject:newArray];
[sectionRowItems insertObject:newArray atIndex:addBtnIndexPath.row];
[self.numericTable reloadData];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return alphabetArray.count
}
Fist of all you are setting CustomCellC in else part. so, when you add new cell if cell indexpath.row is greater then 1 it use CustomCellC
May be you use a same array for all sections. so, when you insert new object in array numberOfRowsInSection will return same count for every section, there for it add new row in every section.
You can set different array for each section and also set number of rows for particular section like this:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (section == 0){
return arr.count;
}else if (section == 1{
return arr1.count;
}
return arr2.count;
}
-(void)insertNewACell:(UIButton *)addButton atIndexPath:(NSIndexPath *)addBtnIndexPath
{
newArray = [[NSMutableArray alloc]init];
[newArray addObject:#"XXXX"];
[newArray addObject:#"YYYY"];
[newArray addObject:#"YYYY"];
if(addBtnIndexPath.section)
[arr addObject:newArray]
}else if(addBtnIndexPath.section){
[arr1 addObject:newArray]
}else{
[arr addObject:newArray]
}
I have a view that has 2 independent cells. Everything is working properly, except the numberOfRowsInSection return that must be different for each cell.
I want my cell "dummy" to only return 1 or 2.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//I need to add some code in here that will say that
//if my cell = dummy then return 1 else
//Returning table count based on number of Team Names
return _teamNames.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0 && indexPath.row == 0) {
return indexPath.row + 20 - indexPath.row;
}
if (indexPath.section == 0 && indexPath.row == 18) {
return indexPath.row + 50 - indexPath.row;
} else {
return indexPath.row + 26 - indexPath.row;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *dummycell = #"dummy";
dummytest *cellar = [tableView dequeueReusableCellWithIdentifier:dummycell
forIndexPath:indexPath];
cellar.righthere.text = #"hello";
static NSString *CellIdentifier = #"StandingsIdent";
StandingsViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
Any ideas? Thank you.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// I need to add some code in here that will say that if my cell = dummy then return 1 else
// You need to set this bool value in your code somewhere - where you have some sort of toggle button between - Dummycell and StandingsViewCell
if(isDummyCell)
{
return 1;
}
else
{
return _teamNames.count; // Returning table count based on number of Team Names
}
}
You can use a NSMutableDictionary as source for your Table View data (i.e. "MyData"), so you can control the behaviour of every cell directly by the data source.
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
//list of elements
if (self.keys.count == 0) {
return 0;
}
NSString *key = [self.keys objectAtIndex:section];
NSArray *mySection = [MyData objectForKey:key];
return [mySection count];
}
where keys is the array that holds your sections. When you load your data, if you want an alphabetical order, you've only to do:
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
[keyArray addObjectsFromArray:[[self.MyData allKeys] sortedArrayUsingSelector:#selector(compare:)]];
self.keys = keyArray;
I have the following code to count the number of selected rows in a table (tableview1).
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
int count = 0;
selectedindex1 = indexPath.row;
for (NSIndexPath *indexPath in tableview1.indexPathsForSelectedRows) {
count = count + 1;
}
rowcount = count;
}
where selectedindex1 and rowcount are integer variables.
This code works as long as you assume that the user won't select a row that has already been selected. If they do, the application can't tell the right number of selected rows because such an action won't trigger the didSelectRowAtIndexPath method. Is there a better way of counting the number of selected rows?
Thank you for your help.
I think it's as simple as this:
[[tableView indexPathsForSelectedRows] count]
Then again, that's exactly what your code does:
int count = 0;
for (NSIndexPath *indexPath in tableview1.indexPathsForSelectedRows) {
count = count + 1;
}
rowcount = count;
What is it exactly that you want to happen?
Maybe just keep a running array of the indexPath's that are selected..That way, you won't ever have to worry about selecting the same one twice.
-Initialize an array in viewDidLoad
NSMutableArray *yourSelectedRowsArray = [[NSMutableArray alloc]init];
-And then in didSelectRowAtIndexPath...do something like this:
if(![yourSelectedRowsArray containsObject:indexPath])
{
[yourSelectedRowsArray addObject:indexPath];
}
NSLog(#"the number of selected rows is %d",yourSelectedRowsArray.count);
-And in didDeselectRowAtIndexPath..do something like:
if([yourSelectedRowsArray containsObject:indexPath])
{
[yourSelectedRowsArray removeObject:indexPath];
}
NSLog(#"the number of selected rows now is %d",yourSelectedRowsArray.count);
Then just access the count of the array wherever you want to use it, and you'll have the number of selected rows.
Okay. It's as simple as the following.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
rowcount = [[tableView indexPathsForSelectedRows] count];
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
rowcount = [[tableView indexPathsForSelectedRows] count];
}
I am using paging with uitableview. I have array of 40 objects. In the numberofrowsinasection method, I am returning 10 rows. Its mean total number of pages is four. Within the pagecontrol method, I am implementing the paging. When I like
-(ibaction) pagecontrol:
{
if (pagecontrol.currentpage == 0)
{
for (int i=0; i<10; i++ )
{
cell.textlabel.text = [objectarray objectatindex:i];
}
}
if (pagecontrol.currentpage == 1)
{
for (int i=10; i<19; i++ )
{
cell.textlabel.text = [objectarray objectatindex:i];
}
}
if (pagecontrol.currentpage == 2)
{
for (int i=20; i<29; i++ )
{
cell.textlabel.text = [objectarray objectatindex:i];
}
}
if (pagecontrol.currentpage == 3)
{
for (int i=30; i<39; i++ )
{
cell.textlabel.text = [objectarray objectatindex:i];
}
}
}
But I found a strange result in uiableview. Is it correct? Where am I doing the mistake in this pagecontrol method?
Do you always have exactly 40 rows or could there be less?
The code you posted starts with a missing method parameter. There should be either no colon or a parameter after the colon (with a data type).
The code you posted suffers from several problems. The biggest issue is you set the text of the same cell 10 times. You need to set the text of 10 cells, one time each.
Regardless of that, you are going about this all wrong. Replace your posted method with this:
-(IBAction)pagecontrol:(UIPageControl *)pageControl {
[self.tableView reloadData];
}
Then, in your tableView:cellForRowAtIndexPath: method you should do the following:
- (void)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableView *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
int base = pagecontrol.currentPage * 10;
int index = base + indexPath.row;
NSString *text = objectArray[index];
cell.textLabel.text = text;
return cell;
}
This is in addition to your numberOfSectionsInTableView: and tableView:numberOfRowsInSection: methods.
That's all you need.
BTW - case matters. Don't type everything in lowercase. Type it in properly with the proper case.
You are using a constant row in paging to use the section in tableview. It differentiates the rows in the page,
like this:
Set the number of sections in tableview:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 4;
}
// Set rows in section
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch(section){
case 0:
return 10;
break;
case 1:
return 10;
break;
.....
.....
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *FirstLevelCell= #"FirstLevelCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:FirstLevelCell];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FirstLevelCell] autorelease];
}
switch([indexPath section]){
case 0:
{
//Add your code
}
break;
case 1:
{
//Add your code
}
break;
.........
.........
.........
.........
.........
}
}
//Reload table view
[self.tableView reloadData];
I've dug through and found several examples of dynamically adding rows to a UITableView just not to a grouped table and I just can't figure this out. I know what I want to do - I have a grouped table with 3 sections. I want to dynamically add an 'Add new item' row/cell to sections 1 and 2 but not 0 when the edit button is selected.
First I'm confused about numberOfRowsInSection. I'm initially loading my table with this.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[[tableData objectAtIndex:section] objectForKey:#"Rows"] count];
}
Do I need to add an if statement for when I'm editing to add a row to the count for those sections when I'm editing? such as:
if (editing) {
return [[[tableData objectAtIndex:section] objectForKey:#"Rows"] count] + 1;
}
And I realize that the above, if correct, would add a row to each section not just 1 and 2. How would I limit that?
Next is my setEditing function. This is where my real problem is. I believe I need to make an array of index paths of the last rows of sections 1 and 2 so that I can insert the new rows below them. The below is wrong, just my experimentation trying to get something inserted somewhere.
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:1];
NSMutableArray* paths = [[NSMutableArray alloc] initWithObjects:indexPath, nil];
NSArray *paths = [NSArray arrayWithObject:
[NSIndexPath indexPathForRow:6 inSection:1]];
if (editing) {
[[self tableView] insertRowsAtIndexPaths:paths
withRowAnimation:UITableViewRowAnimationTop]; }
else {
[[self tableView] deleteRowsAtIndexPaths:paths
withRowAnimation:UITableViewRowAnimationTop]; }
}
That crappy code returns this error:
Invalid update: invalid number of rows
in section 1. The number of rows
contained in an existing section after
the update (5) must be equal to the
number of rows contained in that
section before the update (5), plus or
minus the number of rows inserted or
deleted from that section (1 inserted,
0 deleted).
So I'm a bit lost. IndexPaths and Arrays are new to me. Actually it's all new to me and I do pour over the docs and posts here but I can't say I always understand it. Any help would be appreciated. I also do realize that I still need to configure my cell and commitEditingStyle methods but I think I can figure that out if I can get a handle on understanding index paths and arrays.
thanks
-----EDIT-----
Ok, so I got this for the most part. I've added a new row to my sections when editing:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(self.editing && section != 0) {
int rows = 0;
rows = [[[tableData objectAtIndex:section] objectForKey:#"Rows"] count] + 1;
return rows;
}
else {
int rows = 0;
rows = [[[tableData objectAtIndex:section] objectForKey:#"Rows"] count];
return rows;
}
}
I've figured out how to apply a label to those new rows when in editing mode:
- (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];
}
//configure the cell...
if(self.editing && indexPath.section != 0 && (indexPath.row == [[[tableData objectAtIndex:indexPath.section] objectForKey:#"Rows"] count])) {
cell.textLabel.text = #"Add new Item";
return cell;
}
else
cell.textLabel.text = [[[tableData objectAtIndex:indexPath.section] objectForKey:#"Rows"] objectAtIndex:indexPath.row];
return cell;
And I'm properly setting the last row of my two sections where the row was added to style insert:
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0)
//Can't edit the items in the first section
return UITableViewCellEditingStyleNone;
else
//if it's the last row in sections 1 or 2 make it an Insert item
if(self.editing && indexPath.section != 0 && (indexPath.row == [[[tableData objectAtIndex:indexPath.section] objectForKey:#"Rows"] count])) {
return UITableViewCellEditingStyleInsert;
}
//Everything else in sections 1 or 2 should be Delete style
else
return UITableViewCellEditingStyleDelete;
}
That all works. Of course it doesn't animate and I still need help with that. I think, but I'm not certain that I need to do the insert/delete rows from the setEditing method. What I believe I need to do is make an array to the sections that I'm editing and then insert the rows there. The *paths array below is wrong because I need an array that points to the last rows in sections 1 & 2 and I don't know how to create that array. Or maybe everything I'm thinking is just wrong. Can someone help point the way? Much thanks.
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
NSArray *paths = [NSArray arrayWithObject:
[NSIndexPath indexPathForRow:?? inSection:??]];
if (editing) {
[[self tableView] insertRowsAtIndexPaths:paths
withRowAnimation:UITableViewRowAnimationTop]; }
else {
[[self tableView] deleteRowsAtIndexPaths:paths
withRowAnimation:UITableViewRowAnimationTop]; }
}
Do I need to add an if statement for when I'm editing to add a row to the count for those sections when I'm editing?
Yes, in your tableView:numberOfRowsInSection: method, you should return count + 1 in the editing mode. If you do not want to add a row to section 0 then adjust your if condition, i.e.
if( self.editing && section != 0)
Your second problem is related to the first one. You are inserting a new row to the section 1 but
numberOfRowsInSection still returns 5 for that section. It should return 6.
The methods insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation:
are just to reload the table efficiently and with animation. I suggest you to implementsetEditing:animated function as below for now. Then you should implement your tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath: methods by taking editing state into account. After everything is working properly, you can use insert and delete methods to have more control over which parts of the table are reloaded.
- (void)setEditing:(BOOL)editing animated:(BOOL)animated{
[super setEditing:editing animated:animated];
[self.tableView reloadData];
}
--EDIT--
You are in the correct path. You can get the indexPaths to delete/insert with a code similar to below:
NSArray *paths = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:[[[tableData objectAtIndex:1] objectForKey:#"Rows"] count] inSection:1],
[NSIndexPath indexPathForRow:[[[tableData objectAtIndex:2] objectForKey:#"Rows"] count] inSection:2],
nil
];