checking multiple cells in UITableView - objective-c

I am using two NSMutable Arrays for storing multiple checkmarks..repeatDaysToStore and data1.
This is the code in viewDidLoad method...
for (int i=1; i<=[repeatDaysToStore count]; i++)
{
BOOL isTheObjectThere = [repeatArray containsObject:[repeatDaysToStore objectAtIndex:(i-1)]];
if (isTheObjectThere)
{
NSString *into=[repeatArray objectAtIndex:[repeatArray indexOfObject:[repeatDaysToStore objectAtIndex:(i-1)]]];
[data1 addObject:into];
NSLog(#"check did load");
}
}
and after this I am using data1 array for checking the cells...
- (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];
}
cell.textLabel.text=[repeatArray objectAtIndex:indexPath.row];
tableView.allowsMultipleSelection=YES;
for (int j=1; j<=[data1 count]; j++) {
NSLog(#"%d",[[data1 objectAtIndex:(j-1)]intValue]);
NSLog(#"%d",indexPath.row);
if([data1 indexOfObject:[data1 objectAtIndex:(j-1)]]==indexPath.row)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
and for handling row selections I am using this code in didSelectRowAtIndexPath
{
NSString *myobj=[repeatArray objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
[repeatDaysToStore removeObject:myobj];
[data1 removeObject:myobj];
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[repeatDaysToStore addObject:myobj];
[data1 addObject:myobj];
}
[tableView reloadData];
}
but its not working.Someone please tell me what is wrong?

I think the issue is with cellForRowAtIndexPath: method's following code:
for (int j=1; j<=[data1 count]; j++)
{
NSLog(#"%d",[[data1 objectAtIndex:(j-1)]intValue]);
NSLog(#"%d",indexPath.row);
if([data1 indexOfObject:[data1 objectAtIndex:(j-1)]]==indexPath.row)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
Remove the code and write the condition like:
if([data1 containsObject:[repeatArray objectAtIndex:indexPath.row])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
Also remove the [tableView reloadData]; from didSelectRowAtIndexPath:

I think you need a less-complicated data structure to make this work in a way that's easy to understand.
The data for your table should be an array of objects. Each object should contain at least two properties: one is the information you're going to show in cell.textLabel.text and the other is a BOOL property that says whether or not the object is selected.
When a row is selected, set the BOOL to the opposite of what it currently is and reload your table. In cellForRowAtIndexPath:, just use the current setting of the object for the requested row without going through a secondary array.

Related

Fast-enumeration logic error checking for compare of UITableViewCell

I have a mutable array (editedServiceParts) with two objects in it; I have a table view with about 30 cells in it. I want to check to see if any of table view cells (cell.textLabel.text) appear in the mutable array; if they do, I want to set the cell.accessory to checkmark.
UPDATED This is my code from -cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// get the timeFormat
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *preferencesDict = [[userDefaults dictionaryForKey:#"preferencesDictionary"] mutableCopy];
int iTimeFormat = [[preferencesDict objectForKey:#"timeFormat"] intValue]; // set timeFormat
NSMutableArray *selectedServicesParts = [NSMutableArray new];
NSMutableArray *editedServiceParts = [NSMutableArray new];
NSString *service;
if(tableView.tag == kServicesTableView) { // services array
static NSString *CellIdentifier = #"apptServicesCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell
SingletonServicesArray *sharedServicesArray = [SingletonServicesArray sharedServicesArray]; // list of available services
[cell.textLabel setText:[sharedServicesArray.globalServicesArray objectAtIndex:indexPath.row]]; // move selected row to cell
// separate soServices.text into individual elements
NSString *cleanService;
if(soServices.text.length > 0) {
selectedServicesParts = [[soServices.text componentsSeparatedByString:#","] mutableCopy];
for(int x = 0; x < selectedServicesParts.count; x++) {
cleanService = [selectedServicesParts[x] stringByReplacingOccurrencesOfString:#"," withString:#""];
[editedServiceParts insertObject: cleanService atIndex: x];
}
}
// now, take the editedServicesParts (w/o commas) and mark cell if appropriate
for (int i = 0; i < editedServiceParts.count; i++) { if ([editedServiceParts containsObject:cell.textLabel.text]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
// Remove accessory mark of recycled cells
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
// for (int i = 0; i < editedServiceParts.count; i++) { // total number of rows in list of all available services
//
// for(service in editedServiceParts) {
// if([cell.textLabel.text isEqualToString: service]) {
// cell.accessoryType = UITableViewCellAccessoryCheckmark;
// break;
}
// }
// }
return cell;
}
What's happening is only the first comparison is being found, although there is another that should have been found. I fear I have a logic problem here, and for the life of me, I don't see it. Help would be greatly appreciated!
SD
You can use containsObject: method to avoid looping altogether:
if ([editedServiceParts containsObject:cell.textLabel.text]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
// Remove accessory mark of recycled cells
cell.accessoryType = UITableViewCellAccessoryNone;
}

Unable to add UITextViewCell's accessoryType

I need to get addressability to the UITableView cell so I can set the checkmark if the user has previously selected that row. Initially, the user checks the tableViewCell, I move that to a textField and store it in Core Data. Now if the user wants to change something in the UITableView, I want to be able to show what is already checked or unchecked.
So, I have a UITableView that I present in a UIPopover (outside of -cellForRowAtIndexPath); if a particular cell has a text value equal to an element in a NSArray, I want to set the cell's accessoryType to checked. This is my UPDATED code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// get the timeFormat
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *preferencesDict = [[userDefaults dictionaryForKey:#"preferencesDictionary"] mutableCopy];
int iTimeFormat = [[preferencesDict objectForKey:#"timeFormat"] intValue]; // set timeFormat
if(tableView.tag == kServicesTableView) { // services array
static NSString *CellIdentifier = #"servicesCell"; // servicesCell is just an identifier; not used that I can tell
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell
SingletonServicesArray *sharedServicesArray = [SingletonServicesArray sharedServicesArray]; // initialize
[cell.textLabel setText:[sharedServicesArray.globalServicesArray objectAtIndex:indexPath.row]];
if( ![soServices hasText] ) { // no text in text box
for (int i = 0; i < sharedServicesArray.globalServicesArray.count; i++) {
NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
// if row has been checked, remove the check
UITableViewCell *cell = [servicesTableView cellForRowAtIndexPath:path];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
break;
}
}
}
else { // not empty
for (int i = 0; i < sharedServicesArray.globalServicesArray.count; i++) {
NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
UITableViewCell *cell = [servicesTableView cellForRowAtIndexPath:path];
// if row is in soServices textfield, add a checkmark
if ([soServices.text containsString: sharedServicesArray.globalServicesArray[i]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
}
}
}
return cell;
}
It's not working; I know for sure at least two of the services are in the array, so I should have two cells with checkmarks; I'm getting zilch!. How do I get this to work correctly?
If I get it correctly, this cellForRowAtIndexPath is updating the cells of a DIFFERENT tableView. It would be more logical to add the above code to the cellForRowAtIndexPath of the tableView that needs updating.
In case you are trying to update the cells of that tableView, then the following code would not work:
for (int i = 0; i < sharedServicesArray.globalServicesArray.count; i++) {
NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
UITableViewCell *cell = [servicesTableView cellForRowAtIndexPath:path];
// if row is in soServices textfield, add a checkmark
if ([soServices.text containsString: sharedServicesArray.globalServicesArray[i]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
}
}
Instead, you would write:
for (int i = 0; i < sharedServicesArray.globalServicesArray.count; i++) {
// if row is in soServices textfield, add a checkmark
if ([soServices.text containsString: sharedServicesArray.globalServicesArray[i]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
}
}

table removing index path row values from array

I'm trying to create an array from selected table rows so I can push it to a new view. My issue is deleting an unselected row from the array it throws an error of index beyond bounds, although I have other items selected.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//listOfItems is a Pre Populated Array for the table
NSString *cellValue = [listOfItems objectAtIndex:indexPath.row];
//the array i want my selected items to be added to
NSArray *array = names;
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[names addObject:cellValue];
NSLog(#"ARRAY: %#", array);
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[names removeObjectAtIndex:indexPath.row];
NSLog(#"ARRAY: %#", array);
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
}
How do I find the index number in the array that is being created so it can delete the proper value? Any help would be appreciated :-) Thanks!
-----SOLUTION-----
Here's an alternative way too just in case others were wondering.
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *selected = [listOfItems objectAtIndex:indexPath.row];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[names addObject:selected];
NSLog(#"ARRAY ADDED %#", names);
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[names removeObject:selected];
NSLog(#"ARRAY DELETED %#", names);
}
If your intention is to pass an array of checked cell values to a view, why adding and removing objects at each cell selection? You could easily achieve this just before you're about to present the new view controller. Something like this:
// In whatever method you have to present the new view controller
// ...
NSMutableArray *names = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i < listOfItems.count; i++)
{
if ([self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]].accessoryType == UITableViewCellAccessoryCheckmark) //Change section number if not 0
{
[names addObject:[listOfItems objectAtIndex:i]];
}
}
// Pass the array now to the destination controller
Ps. You still have to manage checking/unchecking of cells (just as you're already doing in the code above).

Incompatible pointer types returning 'UITableViewCell *__strong' from a function with result type 'UITableView *'

I am loading the search results in a tableView in the following manner but I am getting a warning that complains about incompatible pointer types.
What is the mistake in my code below?
// Our tableView containing the search results.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (searchResults == nil) {
return 0;
} else {
return [searchResults count];
}
}
- (UITableView *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SearchResultCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
return cell;
}
// END tableView
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
NSLog(#"The search text is: '%#'", searchBar.text);
searchResults = [NSMutableArray arrayWithCapacity:10];
for (int i = 0; i < 3; i++) {
[searchResults addObject:[NSString stringWithFormat:#"Fake Result %d for '%#'", i, searchBar.text]];
}
[self.tableView reloadData];
}
The return type of tableView:cellForRowAtIndexPath: is incorrect. It should be UITableViewCell * instead of UITableView *.

How to remove a button from UITableViewCell?

I have customized a UITableViewCell in that I have a UILabel and UIButton. I have set the frame in layoutSubviews method now that table has customized UITableViewCell that I am using in three places, but I need to remove UIButton in second place. How to do that ?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomPopTableViewCell *cell = (CustomPopTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[CustomPopTableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
cell.accessoryType = UITableViewCellAccessoryNone;
if(tableView.tag == e_metadataView)
{
//cell.mCheakMarkButton.frame=CGRectZero;
cell.mTaggedTerm.text = [docInfoCollection objectAtIndex:indexPath.row];
}
else if(tableView.tag == e_searchSettingView)
{
if(indexPath.row == self.currentRow)
{
[cell.mcheckMarkButton removeFromSuperView];
}
cell.mTaggedTerm.text = [searchEngineCollection objectAtIndex:indexPath.row];
}
else if(tableView.tag == e_TaggedTermView)//tageed term table
{
TaggedItems *taggedItem = [documentData.taggedWords objectAtIndex : indexPath.row];
cell.mTaggedTerm.text = taggedItem.keyword;
if([self isTappedObjectExist:indexPath.row])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
return cell;
}
I would use :
for (UIView* v in cell.subviews) {
if ([v isKindOfClass:[UIButton class]]) {
[v removeFromSuperView];
}
}
To be amended if you have an intermediary level of view in your custom cell of course. If you have several buttons I would use a tag to identify it.