Counting the number of selected rows on UITableView - ios

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];
}

Related

Auto Increment to each cell in different section table

I want to set a number to each cell in the table view, and i have diffent section so can't use indexPath.row.
Currently im using one variable count and increasing it in cellForRowAtIndexPath count++.
but it refresh when im scrolling table.
SO how to set auto increament number to each cell.
Try this on cellForRowAtIndexPath.. Will calculate previous sections and its row and adds with current row
NSInteger cellNumber = indexPath.row;
for (int i =0; i<indexPath.section; i++) {
cellNumber += [tableView numberOfRowsInSection:i];
}
The instance variable won't work. Your index should be calculable, as your problem states, from the indexPath (row and section), lacally within cellForRowAtIndexPath.
Try this:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"identifier"];
NSInteger count = 0;
for (NSInteger sec=0; sec < indexPath.section; sec++) {
NSInteger rows = [tableView numberOfRowsInSection:sec];
count += rows;
}
count += indexPath.row + 1;
NSLog(#"Current row is: %ld", (long)count);
return cell;
}
copy and paste the code:-
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:#"Cell"];
}
// Configure the cell...
NSInteger cellNumber = indexPath.row;
for (int i =0; i<indexPath.section; i++) {
cellNumber += [tableView numberOfRowsInSection:i];
}
cell.textLabel.text = [NSString stringWithFormat:#"%ld", (long)cellNumber];
return cell;
}
Try a combination of
NSString *string = [NSString stringWithFormat:#"%#%#",#(indexPath.section),#(indexPath.row)];
cell.tag = [string intValue];
You'll always get a unique number that you can use for reference.

How to manipulate array in section?

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.

Prompt on the last cell of the table view

I want UITableView always has the text "No more items" in the last cell, I want this row appears regardless of number of items, include 0 items. How could I do?
You can get the total row of a section by using numberOfRowsInSection: method.
NSInteger total = [self.tableView numberOfRowsInSection:indexPath.section];
// Check if last cell or no cell.
if(indexPath.row == totalRow -1 || indexPath.row == 0)
{
// Do your operation here
}
You can perform this in your cellForRowAtIndexPath or willDisplayCell methods. Hope it helps.
Just add the row regardless of your other items:
- (void)buildMenu {
[_menuItems removeAllObjects];
// ... add your items or not if you have 0
YourCellItem *lastItem = [[YourCellItem alloc] initWithTitle:#"No more items"];
[_menuItems addObject:lastItem];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _menuItems.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"yourCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
YourTableViewCell *basicCell = (YourTableViewCell *)cell;
YourCellItem *item = [_menuItems objectAtIndex:indexPath.row];
basicCell.itemTitle.text = item.title;
return cell;
}

Counting the amount of sections in tableView

I want show the amount of sections of a tableView somewhere as a badge.
The first problem is that I get a outcome of 0.
I've declared a int in the TableViewController.h as section.
In the .m file:
- (void)viewDidAppear:(BOOL)animated
{
self.section = [self.tableView numberOfSections];
NSLog(#"Number of sections in tableView are %d", self.section);
}
Why do I still get a 0 as outcome?
Is there somewhere in the numberOfSectionsInTableView I need to count the amount of sections?
Thanks
Update:
In the tableView I set al the scheduledLocalNotifications.
I made a set of 2 notifications which are linked to each other.
So 2 rows of scheduledLocalNotifications in each section.
This is what I have in the tableView:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return (int)[[[UIApplication sharedApplication] scheduledLocalNotifications] count]/2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 2;
}
- (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];
}
// Configure the cell...
int rowIndex = (indexPath.section*2) + indexPath.row;
// Get list of local notifications
NSArray *localNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications];
UILocalNotification *localNotification = [localNotifications objectAtIndex:rowIndex];
return cell;
}
You can find number of sections in any tableview after numberOfSectionsInTableView method call. So, initialize your variable in numberOfSectionsInTableView method before return statement.

How to create a dynamic size array

What I am trying to achieve:
I have a UITableView and I want to check whether the table was selected or not and keep in an array easy to access the YES or NO values that corresponds to that row so that afterwards i can manipulate the data.
my code as follows
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellLabelText = cell.textLabel.text;
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
selected[row] = NO;
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
selected[row] = YES;
}
}
As it stands out I can create a BOOL selected[some value] but my problem is that the max index needed for me is unknown as my table size changes constantly. thus setting the max index limits me.
I am new to objective C and I come from a PHP background thus I dont know whether it is possible to create an array that does what i want to do in objective-c.
Otherwise what would be my options within objective-c to have an easy way to easy write/read selected[row] = YES/NO.
I need a way to write YES/NO and link it to the indexpath.row
Use an NSMutableSet and store the NSIndexPath of the selected rows. If you select a row you add the path to the set. If you unselect a row, remove the path from the set.
To see if a row is selected, see if the indexPath is in the set or not.
BTW - this only works if the rows are fixed. If the user can add, remove, or reorder rows then this approach will not work. In such a case you need to store data keys, not index paths.
Create an ivar of type NSMutableSet. Let's call it selectedRows:
selectedRows = [[NSMutableSet alloc] init];
Then in didSelectRow you do:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL selected = [selectedRows containsObject:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellLabelText = cell.textLabel.text;
if (selected) {
cell.accessoryType = UITableViewCellAccessoryNone;
[selectedRows removeObject:indexPath];
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[selectedRows addObject:indexPath];
}
}
In your cellForRow... method you do something similar:
BOOL selected = [selectedRows containsObject:indexPath];
cell.accessoryType = selected ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
Just use
NSMutableArray *dynamicArray = [NSMutableArray array];
You can add and delete objects from this at will. Just be sure to use the NSNumber wrapper to add primitives:
[dynamicArray addObject:[NSNumber numberWithInt:indexNumber]];
// or
[dynamicArray addObject:#(indexNumber)];
Instead of an array you can use a index set.
#property (nonatomic,strong) NSMutableIndexSet *pickedIndexPaths;
- (void)viewDidLoad
{
_pickedSIndexPaths = [[NSMutableIndexSet alloc] init];
[super viewDidLoad];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//…
if(indexPath.section == 0) {
cell.textLabel.text = self.sports[indexPath.row][#"sport"][#"name"];
if ([_pickedIndexPaths containsIndex:indexPath.row]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([_pickedIndexPaths containsIndex:indexPath.row]) {
[_pickedIndexPaths removeIndex:indexPath.row];
} else {
[_pickedIndexPaths addIndex:indexPath.row];
}
[tableView reloadData];
}
}
When what you need is a variable length array of boolean values, you can use CFBitVectorRef. This will consume much less memory than using a Cocoa collection designed for objc object values (provided of course that array has many elements) because it consumes 1 bit for each value, rather than a full pointer which points to an individual dynamically allocated reference counted object.

Resources