hey i have created a table view with multiple selection and checkmark accessory which users can tap on and select relevant rows in table... retailerid and retailernaem of individual selection will be stored in NSMutableDictionary and all dictionaries in return will be stored in NSMutableArray... i have done this till now
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
NSMutableDictionary *theDictionary = [[NSMutableDictionary alloc] init];
[theDictionary setObject:[[BrandsArray valueForKey:#"RetailerID"] objectAtIndex:indexPath.row] forKey:#"id"];
[theDictionary setObject:[[BrandsArray valueForKey:#"RetailerName"] objectAtIndex:indexPath.row] forKey:#"name"];
[selectedIndexes addObject:theDictionary];
}
else {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
NSLog(#"this is deselected row %#",[selectedIndexes objectAtIndex:indexPath.row]);
NSMutableDictionary *dictionary = [selectedIndexes objectAtIndex:indexPath.row];
[selectedIndexes removeObject:dictionary];
dictionary = nil;
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
now problem is in the else block... its not removing objects from randomly selected row...
for example if i select first row and then deselect the same it works fine but when i select the last row and then deselect the same app crash..
Since my other answer dealt with multiple sections, I will provide a simpler, single section answer here
First, declare a property for your selection state -
#property (strong,nonatomic) NSMutableIndexSet *selectStates;
Initialise it in viewDidLoad
self.selectStates=[NSMutableIndexSet new];
The use it in didSelectRowAtIndexPath -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([self.selectStates containsIndex:[indexPath.row]) {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[self.selectStates removeIndex:indexPath.row];
} else {
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.selectStates addIndex:indexPath.row];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
You will also need to check the selectedStates in cellForRowAtIndexPath to set the correct accessory when the cell is scrolled back into view. Just add the snippet -
if ([self.selectStates containsIndex:[indexPath.row]) {
[cell setAccessoryType:UITableViewCellAccessoryNone];
} else {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
If you need the ability to easily insert and delete rows then you can use an NSMutableSet instead of an NSIndexSet - just store the data source object. If you do allow deletion you need to make sure that the object is removed from the set, if necessary, when the row is deleted.
First, declare a property for your selection state -
#property (strong,nonatomic) NSMutableSet *selectStates;
Initialise it in viewDidLoad
self.selectStates=[NSMutableSet new];
The use it in didSelectRowAtIndexPath -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
Brand *brand=(Brand *)[BrandsArray objectAtIndex:indexPath.row]; // Change "Brand" to the appropriate object class
if ([self.selectStates containsObject:brand) {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[self.selectStates removeObject:brand];
} else {
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.selectStates addObject:brand];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
You will also need to check the selectedStates in cellForRowAtIndexPath to set the correct accessory when the cell is scrolled back into view. Just add the snippet -
if ([self.selectStates containsObject:brand) {
[cell setAccessoryType:UITableViewCellAccessoryNone];
} else {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
The problem is the way you use the array.
Let's say you select the last element from a table view with 10 cells. Then the array size is 1, but when you select again the last row, [selectedIndexes objectAtIndex:indexPath.row]; is trying to access the element with index 9 in the array, which does not exist at the moment.
Try to implement something like this:
NSInteger ARRAY_INITIAL_SIZE = 100;
NSMutableArray *selectedIndexes = [NSMutableArray arrayWithCapacity:ARRAY_INITIAL_SIZE];
for (NSInteger i = 0; i < ARRAY_INITIAL_SIZE; ++i) {
selectedIndexes[i] = [NSNull null];
}
Make selectedIndexes to be a property in your View Controller class, and whenever you use it, put self.selectedIndexes instead.
In the didSelectRow: atIndexPath: method, the first line is recommended to be:
[tableView deselectRowAtIndexPath:indexPath animated:NO];
Then, write the code:
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
NSMutableDictionary *theDictionary = [NSMutableDictionary dictionary];
[theDictionary setObject:[[BrandsArray valueForKey:#"RetailerID"] objectAtIndex:indexPath.row] forKey:#"id"];
[theDictionary setObject:[[BrandsArray valueForKey:#"RetailerName"] objectAtIndex:indexPath.row] forKey:#"name"];
[selectedIndexes replaceObjectAtIndex:indexPath.row withObject:theDictionary];
} else {
selectedCell.accessoryType = UITableViewCellAccessoryNone;
[selectedIndexes replaceObjectAtIndex:indexPath.row withObject:[NSNull null]];
}
I hope it helps you. Let me know.
Related
I just saw a post about selecting multiple UITableView rows and based on which row/rows are selected, something will happen when you press a button linked to an IBAction.
It's an interesting question and I've played around with it, but now I'm stuck a bit.
As you can see I have a NSMutableArray called selectedIndexes, and the selected row/rows are shown in the console using a NSLog. This works fine:
- (IBAction)doSomethingWithSelectedRows:(id)sender {
for (NSNumber *data in self.selectedIndexes) {
NSLog(#"Row %ld is selected.", (long)[data integerValue] +1);
}
if (WHAT SHOULD BE PUT HERE?) {
}
//Do whatever you want here.
}
The question is, what should be put in that if statement above if you want this to happen:
if (row 2 and row 1 are selected {
//Run this code.
}
UPDATE:
Here's more code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[_selectedIndexes addObject:[NSNumber numberWithInteger:indexPath.row]];
} else {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[_selectedIndexes removeObject:[NSNumber numberWithInteger:indexPath.row]];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (IBAction)doSomethingWithRowsSelected:(id)sender {
for (NSNumber *data in self.selectedIndexes) {
NSLog(#"Row %ld is selected.", (long)[data integerValue] +1);
}
}
While you can use an array, as you do, an NSMutableIndexSet is a much better data structure for this task. It allows you to check whether a given index is in the set without having to iterate through all of the objects.
#property (strong,nonatomic) NSMutableIndexSet *selectedRows;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = indexPath.row;
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([self.selectedRows containsIndex:row]) {
[self.selectedRows removeIndex:row];
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
} else {
[self.selectedRows addIndex:indexPath.row];
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Now you can easily check if any two rows are selected:
- (IBAction)doSomethingWithRowsSelected:(id)sender {
if ([self.selectedRows containsIndex:1] && [self.selectedRows containsIndex:2]) {
// Do whatever
}
}
Also, don't forget to set the accessory type in cellForRowAtIndexPath based on [self.selectedRows containsIndex:indexPath.row] otherwise your checkmarks will be wrong when you scroll.
Here is what I will do,
1st, get the array of selected rows by using indexPathsForSelectedRows,
2nd, iterate the array to check if if indexPath.row is 1 or 2.
3rd, if your if statement's condition is true, then do ...
I have a table view with 5 sections and I have set the tableview selection to multiple. Each section have different number of rows. What I want is to set that the user can select only one cell from each section(in my table user can select any number of cells).
ex: 5 cells from 5 sections.
It should be impossible to select more than one cell from any section. If user select another cell from same section, previously selected cell should be deselected. How can I do this. This is a sample implementation of didSelectRowAtIndexPath.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
HoteldetalcelloneTableViewCell *cellone = (HoteldetalcelloneTableViewCell *)[self.detailtableView cellForRowAtIndexPath:indexPath];
HoteldetailcelltwoTableViewCell *celltwo = (HoteldetailcelltwoTableViewCell *)[self.detailtableView cellForRowAtIndexPath:indexPath];
//I have implement for two sections to test.
if(indexPath.section == 0)
{
HotelDetailsone *secone = [roomonearray objectAtIndex:indexPath.row];
HoteldetailsforBooking *book = [HoteldetailsforBooking new];
if([secone.offerallow isEqualToString:#"True"])
{
celltwo.selectedsignLabel.hidden = NO;
}
else
{
cellone.selectedsignLabelone.hidden = NO;
}
// [self.detailtableView reloadData];
NSLog(#"price for room 1 : %#", secone.itempriceText);
}
else
{
HotelDetailsone *sectwo = [roomtwoarray objectAtIndex:indexPath.row];
HoteldetailsforBooking *book = [HoteldetailsforBooking new];
if([sectwo.offerallow isEqualToString:#"True"])
{
celltwo.selectedsignLabel.hidden = NO;
}
else
{
cellone.selectedsignLabelone.hidden = NO;
}
// [self.detailtableView reloadData];
NSLog(#"price for room 1 : %#", sectwo.itempriceText);
}
}
You need to keep track on the selection of cell. So you need to store selected indexpath in array.
in ViewController.h declare property like this
#property(nonatomic,strong) NSMutableDictionary *selectionData;
Now in ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.selectionData=[[NSMutableDictionary alloc]init];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"mycell"];
if ([self.selectionData objectForKey:[NSString stringWithFormat:#"%ld",(long)indexPath.section] ] != nil) {
NSMutableArray *sectionData=[[self.selectionData objectForKey:[NSString stringWithFormat:#"%ld",(long)indexPath.section]] mutableCopy];
if (![sectionData containsObject:[NSNumber numberWithLong:indexPath.row]])
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.numberlabel.text = #"2";
}
else
{
cell.numberlabel.text = #"***";
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}
}
else
{
cell.numberlabel.text = #"2";
cell.accessoryType = UITableViewCellAccessoryNone;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"selected section :%li ---> selected row :%li",(long)indexPath.section, (long)indexPath.row);
[self handleSelectionForSection:indexPath.section row:indexPath.row];
[self.tablev reloadData];
}
-(void)handleSelectionForSection:(long)sectionIndex row:(long)rowIndex
{
if ([self.selectionData objectForKey:[NSString stringWithFormat:#"%ld",sectionIndex] ] != nil) {
NSMutableArray *sectionData=[[self.selectionData objectForKey:[NSString stringWithFormat:#"%ld",sectionIndex]] mutableCopy];
if (![sectionData containsObject:[NSNumber numberWithLong:rowIndex]])
{
//removing previous selected rows
[sectionData removeAllObjects];
[sectionData addObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:#"%ld",sectionIndex]];
}
else
{
//cell you tapped is already selected,
// you can deselect it by removing object
//if you dont want to deselect it comment following lines
[sectionData removeObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:#"%ld",sectionIndex]];
}
}
else
{
//section key not available so we need to create it
NSMutableArray *sectionData=[[NSMutableArray alloc]init];
[sectionData addObject:[NSNumber numberWithLong:rowIndex]];
[self.selectionData setObject:sectionData forKey:[NSString stringWithFormat:#"%ld",sectionIndex]];
}
NSLog(#"All Selection : %#",self.selectionData);
}
Your numberOfRowsInSection, numberOfSectionsInTableView and titleForHeaderInSection will remain same.
Let me know if you have any query.
You can set selection property of tableview from interface builder. Select your tableview in IB and then select attribute inspector and setsingle selectiontoselection` property like below screenshot.
Or you can set programattically,
self.tableView.allowsMultipleSelection = NO;
Update :
If you want single selection per section then you can implement willSelectRowAtIndexPath as below,
- (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath {
for ( NSIndexPath* selectedIndexPath in tableView.indexPathsForSelectedRows ) {
if ( selectedIndexPath.section == indexPath.section )
[tableView deselectRowAtIndexPath:selectedIndexPath animated:NO] ;
}
return indexPath ;
}
In this case you should allow multiple selection in tableview i think.
Reference : Answer of John Sauer
Looks like you are updating celltwo / cellone selectedsignLabel.hidden on table selection. so #Lion solution will not working. You have to save the last selected index using below code :
#property (nonatomic, strong) NSMutableDictionary *selectedIndexPathDict;
// in viewDidLoad:
self.tableView.allowsMultipleSelection = YES;
self.selectedIndexPathDict = [[NSMutableDictionary alloc] init];
//In table view delegate.
- (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath {
NSString *indexSection = [NSString stringWithFormat:#"%ld", (long)indexPath.section];
NSIndexPath *indexPath1 = self.selectedIndexPathDict[indexSection];
if ( indexPath1) {
HotelDetailsone *secone = [roomonearray objectAtIndex:indexPath.row];
secone.offerallow ^= YES; //toggle bool value
// update new selected index path.
[self.selectedIndexPathDict setObject:indexPath forKey:indexSection];
//reload previous selected cell.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:#[indexPath1] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
});
} else {
//initialise selected index path
self.selectedIndexPathDict[indexSection] = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:NO] ;
return indexPath ;
}
I have not update the complete working code. But this is the way to achieve. You can also use the userdefault instead of self.selectedIndexPathDict.
I've been trying to selection of cell like
Same As Checkbox To select elements from object array
Here is my code. Please guide me.. Thanks in advance
#import <UIKit/UIKit.h>
#interface CheckAllListViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
{
IBOutlet UITableView *_myTable;
NSMutableArray *_myArray;
NSMutableArray *_selectedArray;
}
#property(nonatomic,retain) UITableView *myTable;
#property(nonatomic,retain)NSMutableArray *myArray;
#property(nonatomic,retain)NSMutableArray *selectedArray;
-(void)checkmarkAll;
-(void)UnChceckAll;
CheckAllListViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
_myArray=[[NSMutableArray alloc]initWithObjects:#"Check All",#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10" ,nil];
_selectedArray=[[NSMutableArray alloc]init];
// Do any additional setup after loading the view from its nib.
}
#pragma mark -UITableViewDelegates & Datasource
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedArray addObject:[self.myArray objectAtIndex:indexPath.row]];
//if 'all' row is selected then check all rows
if([[self.myArray objectAtIndex:indexPath.row] isEqualToString:#"Check All"])
{
[self checkmarkAll];
}
}
else if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedArray removeObject:[self.myArray objectAtIndex:indexPath.row]];
if([[self.myArray objectAtIndex:indexPath.row] isEqualToString:#"Check All"])
{
[self UnChceckAll];
[self.selectedArray removeAllObjects];
}
else if([self.selectedArray containsObject:#"Check All"])
{
[self checkmarkAll];
[self.selectedArray removeAllObjects];
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedArray addObject:[self.myArray objectAtIndex:indexPath.row]];
}
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [_myTable dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if([self.selectedArray count])
{
if([self.selectedArray containsObject:[self.myArray objectAtIndex:indexPath.row]] || [self.selectedArray containsObject:#"Check All"])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
cell.textLabel.text=[_myArray objectAtIndex:indexPath.row];
// [self configureCell:cell atIndexPath:indexPath];
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _myArray.count;
}
-(void)checkmarkAll
{
for (int i=0;i<[self.myArray count] ; i++)
{
NSIndexPath *myIdx=[NSIndexPath indexPathForRow:i inSection:0];
UITableViewCell *cell=[self.myTable cellForRowAtIndexPath:myIdx];
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}
}
-(void)UnChceckAll
{
for(int i=0;i<[self.myArray count];i++)
{
NSIndexPath *myIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
UITableViewCell *cell = [self.myTable cellForRowAtIndexPath:myIndexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
I've used this tutorial -http://iphonediscoveries.blogspot.in/2013/10/creating-inclusive-list-in-uitableview.html
I want to achieve :
1 Add an option for the user to be able to select all rows when ‘all’ is selected.
2 When the ‘all’ is checked I want all rows checkmarked, and all checkmarks removed when 'all' is unchecked.
3 When ‘all’ is checked, and all rows are checkmarked, if at that time a row is clicked, then check marks in all other rows should be removed (including ‘all’) and only that row should contain the checkmark.
4 Should not forget Selection After calling and scrolling UITableview
UPDATE
-My Following code gives me check all functionality & Uncheck All Functionality .
Lets say I've chosen all row by selecting check all now,If I'd choose any row randomly Should remove tick from current selected element & as well should remove tick from first element i.e #"Check All"
-same for uncheck functionality
Not sure if I get what the problem is, but I would change the checkAll and uncheckAll methods to change the selectedArray and reload the tableview:
-(void)checkmarkAll
{
self.selectedArray = [NSMutableArray arrayWithArray:self.myArray];
[self.tableView reloadData];
}
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.
I have a list which I have using as a check boxes. I have enable or disable Check mark on row on select. But when I scroll the list its make mark row after every 10 rows.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:indexPath];
if (oldCell.accessoryType == UITableViewCellAccessoryCheckmark)
{
oldCell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
oldCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
UItableView reuses the cell in every scroll so using condition as per accessory type is not a good practice. You can Create an NSMutableArray with selected items and Check as per the Condition below.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if ([selected containsIndex:indexPath.row]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
// Do the rest of your code
return cell;
}
in didSelectrowAtindexpath method you can Add and remove the Selected items.
Its because UITableView reuses the cell.
So, in the method cellForRowAtIndexPath, you will have to check for a particular cell (of a particular section and row), if it needs to be checked on, provide the accessory type.
If not needed for that cell, provide accessory type as none.
You need to put your logic to set accessory type for cell in cellForRowAtIndexPath, and to identify the cell to mark with check mark you can mark the object in the list in didSelectRowAtIndexPath: or manage an array of selected/unselected objects of the list here.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[NSMutableArray addObject:[AnotherMutableArray objectAtIndex:indexPath.row]];
} else {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[NSMutableArray removeObject:[AnotherMutableArray objectAtIndex:indexPath.row]];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
Also in your viewDidLoad, instantiate you both mutable arrays-
yourmutableArray1 = [[NSMutableArray alloc]init];
yourmutableArray2 = [[NSMutableArray alloc]init];