having error with custom checkboxes in uitableview cells - iphone

im getting the error: * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update'*
I have 2 sections and I am trying to make it so when you click the checkbox of a cell in one of the sections, it goes to the other section (ex: section 1->section 2)
here is some relevant code of mine:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"UITableViewCell"];
if([indexPath section] == 0){
cell.textLabel.text = [[[taskArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
cell.imageView.image = [UIImage imageNamed:#"checkboxtry2.png"];
} else if ([indexPath section] == 1) {
cell.textLabel.text = [[[completedArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
cell.imageView.image = [UIImage imageNamed:#"checkboxtry2selected.png"];
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handlechecking:)];
[cell.imageView addGestureRecognizer:tap];
cell.imageView.userInteractionEnabled = YES;
return cell;
}
-(void)handlechecking:(UITapGestureRecognizer *)t{
CGPoint tapLocation = [t locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
if (tappedIndexPath.section == 0) {
[completedArray addObject:[taskArray objectAtIndex:tappedIndexPath.row]];
[taskArray removeObject:[taskArray objectAtIndex:tappedIndexPath.row]];
}
else {
[taskArray addObject:[completedArray objectAtIndex:tappedIndexPath.row]];
[completedArray removeObject:[completedArray objectAtIndex:tappedIndexPath.row]];
}
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:tappedIndexPath] withRowAnimation: UITableViewRowAnimationFade];
}
I have two arrays: taskArray which handles objects in section 0 and completedArray which handles objects in section 1.
---EDIT---
Here is what I have now:
TableViewController.h
#interface ToDoTableViewController : UITableViewController <Properties2ViewControllerDelegate, UITableViewDelegate, SettingsViewControllerDelegate>
#property (strong, nonatomic) NSMutableArray *taskArray;
#property (strong, nonatomic) NSMutableArray *completedArray;
#property (strong, nonatomic) NSMutableArray *holdViewsArray;
-(IBAction)addCell:(id)sender;
-(void)buttonPressed:(id)sender;
-(void)handlechecking:(UITapGestureRecognizer *)t;
TableViewController.m
-(void) viewDidLoad{
[self.tableView setDelegate:self];
[self setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
taskArray = [[NSMutableArray alloc] init];
completedArray = [[NSMutableArray alloc]init];
holdViewsArray = [[NSMutableArray alloc]init];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"UITableViewCell"];
NSString *detailText = [NSString stringWithFormat:#"%.0f", [[taskArray objectAtIndex:[indexPath row]] timeInterval]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
[cell setBackgroundColor:[UIColor colorWithRed:236.0/255 green:240.0/255 blue:241.0/255 alpha:1.0f]];
cell.textLabel.textColor = baseColor;
[[cell detailTextLabel] setText:detailText];
[[cell detailTextLabel] setFont:[UIFont fontWithName:#"Avenir-Black" size:12]];
[[cell textLabel] setFont:[UIFont fontWithName:#"AvenirNext-DemiBold" size:16]];
if([indexPath section] == 0){
cell.textLabel.text = [[[taskArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
cell.imageView.image = [UIImage imageNamed:#"unchecked.png"];
} else if ([indexPath section] == 1) {
cell.textLabel.text = [[[completedArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
cell.imageView.image = [UIImage imageNamed:#"checked.png"];
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handlechecking:)];
[cell.imageView addGestureRecognizer:tap];
cell.imageView.userInteractionEnabled = YES;
return cell;
}
-(void)handlechecking:(UITapGestureRecognizer *)t{
CGPoint tapLocation = [t locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
NSIndexPath *newIndexPath = nil;
if (tappedIndexPath.section == 0) {
NSUInteger newRowIndex = self.completedArray.count;
[self.completedArray addObject:[self.taskArray objectAtIndex:tappedIndexPath.row]];
[self.taskArray removeObject:[self.taskArray objectAtIndex:tappedIndexPath.row]];
newIndexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:1];
} else {
NSUInteger newRowIndex = self.taskArray.count;
[self.taskArray addObject:[self.completedArray objectAtIndex:tappedIndexPath.row]];
[self.completedArray removeObject:[self.completedArray objectAtIndex:tappedIndexPath.row]];
newIndexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:0];
}
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView deleteRowsAtIndexPaths:#[tappedIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSInteger num = 0;
if (section == 0) {
num = self.taskArray.count;
} else {
num = self.completedArray.count;
}
return num;
}
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
Tasks *taskToMove = [taskArray objectAtIndex:[sourceIndexPath row]];
if (sourceIndexPath.row > destinationIndexPath.row) {
[taskArray insertObject:taskToMove atIndex:destinationIndexPath.row];
[taskArray removeObjectAtIndex:(sourceIndexPath.row + 1)];
}
else if (sourceIndexPath.row < destinationIndexPath.row) {
[taskArray insertObject:taskToMove atIndex:(destinationIndexPath.row + 1)];
[taskArray removeObjectAtIndex:(sourceIndexPath.row)];
}
}
-(IBAction)addCell:(id)sender{
Properties2ViewController *pvc = [[Properties2ViewController alloc]init];
[pvc setDelegate:self];
[self presentViewController:pvc animated:YES completion:NULL];
[pvc setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
}
-(void)properties2ViewControllerDidEnterPropertiesSuccesfully:(Tasks *)t{
if (![[t taskName] isEqual: #""]) {
[taskArray addObject:t];
}
[self.tableView reloadData];
}
Properties2ViewController.m
-(IBAction)dismiss:(id)sender{
testTask = [[Tasks alloc]init];
testTask.taskName = taskName.text;
testTask.timeInterval = datePicker.countDownDuration;
testTask.dateCreated = [NSDate date];
if ([self.delegate respondsToSelector:#selector (properties2ViewControllerDidEnterPropertiesSuccesfully:)]){
[self.delegate properties2ViewControllerDidEnterPropertiesSuccesfully:testTask];
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
Properties2viewcontroller is a modal controller that adds a Task object to the taskArray.

You are trying to reload rows but what you actually want to do is delete row from section 0 and add it to section 1 or vise versa. So in handlechecking method you must write something like this:
-(void)handlechecking:(UITapGestureRecognizer *)t{
CGPoint tapLocation = [t locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
NSIndexPath *newIndexPath = nil;
if (tappedIndexPath.section == 0) {
NSUInteger newRowIndex = self.sectionTwoArr.count;
[self.sectionTwoArr addObject:[self.sectionOneArr objectAtIndex:tappedIndexPath.row]];
[self.sectionOneArr removeObject:[self.sectionOneArr objectAtIndex:tappedIndexPath.row]];
newIndexPath = [NSIndexPath indexPathForRow:newRowindex inSection:1];
} else {
NSUInteger newRowIndex = self.sectionOneArr.count;
[self.sectionOneArr addObject:[self.sectionTwoArr objectAtIndex:tappedIndexPath.row]];
[self.sectionTwoArr removeObject:[self.sectionTwoArr objectAtIndex:tappedIndexPath.row]];
newIndexPath = [NSIndexPath indexPathForRow:newRowindex inSection:0];
}
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView deleteRowsAtIndexPaths:#[tappedIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
Edit
Full implementation of other methods
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.sectionOneArr = [#[#"ololo", #"dsd", #"dsdfsf"] mutableCopy];
self.sectionTwoArr = [#[#"ototo",#"dd", #"sdfsdfsd"] mutableCopy];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger num = 0;
if (section == 0) {
num = self.sectionOneArr.count;
} else {
num = self.sectionTwoArr.count;
}
return num;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"UITableViewCell"];
if([indexPath section] == 0){
cell.textLabel.text = [[self.sectionOneArr objectAtIndex:[indexPath row]] uppercaseString];
cell.imageView.image = [UIImage imageNamed:#"unchecked.jpeg"];
} else if ([indexPath section] == 1) {
cell.textLabel.text = [[self.sectionTwoArr objectAtIndex:[indexPath row]] uppercaseString];
cell.imageView.image = [UIImage imageNamed:#"checked.jpeg"];
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handlechecking:)];
[cell.imageView addGestureRecognizer:tap];
cell.imageView.userInteractionEnabled = YES;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString * num = nil;
if (section == 0) {
num = #"One";
} else {
num = #"Two";
}
return num;
}

Your code looks correct but I would venture a guess that the problem is in your tableView:numberOfRowsInSection: method. Are you returning the proper count of rows for each section? Should look like this:
if([indexPath section] == 0){
return [taskArray count];
} else {
return [completeArray count];
}

Related

TableView isn't updating data even though it recognizes input?

So I have 5 rows and on selection they pass an integer with the row number to my second view controller.
Each number has its own array with items and should then return the amount of items for the row specified.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MasterCell";
MasterCell *cell = (MasterCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
if (radInt == 0) {
cell.textLabel.text = #"LM";
NSLog(#"My return should have been LM");
}
if (radInt == 1) {
cell.textLabel.text = #"Restauranger";
NSLog(#"My return should have been Rest");
}
if (radInt == 2) {
cell.textLabel.text = [shoppingArray objectAtIndex:indexPath.row];
}
if (radInt == 3) {
cell.textLabel.text = [annatArray objectAtIndex:indexPath.row];
}
//cell.textLabel.text = [listData objectAtIndex:[indexPath row]];
cell.imageView.image = [UIImage imageNamed:#"tab-icon1.png"];
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
This is my code just to test it out and it doesn't work. NSLOG works correctly but the data simply wount update... What have I done wrong? It Nslogs LM every time but it also has 1 in the log which is the selected row (radInt).
New approach
static NSString *CellIdentifier = #"MasterCell";
MasterCell *cell = (MasterCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil)
cell = [[MasterCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if (radInt == 0) {
cell.textLabel.text = #"LM";
NSLog(#"My return should have been LM");
}
else if (radInt == 1) {
cell.textLabel.text = #"Restauranger";
NSLog(#"My return should have been Rest");
}
else if (radInt == 2) {
cell.textLabel.text = [shoppingArray objectAtIndex:indexPath.row];
}
else if (radInt == 3) {
cell.textLabel.text = [annatArray objectAtIndex:indexPath.row];
}
else {
cell.textLabel.text = #"Noes";
}
//cell.textLabel.text = [listData objectAtIndex:[indexPath row]];
cell.imageView.image = [UIImage imageNamed:#"tab-icon1.png"];
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
The view before ----
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SecondViewController *enjoy = [[SecondViewController alloc] init];
if ([[array objectAtIndex:indexPath.row] isEqual:#"Livsmedel"]) {
[enjoy setTitle:[array objectAtIndex:indexPath.row]];
enjoy.radInt = 0;
NSLog(#"0");
}
if ([[array objectAtIndex:indexPath.row] isEqual:#"Restauranger"]) {
[enjoy setTitle:[array objectAtIndex:indexPath.row]];
enjoy.radInt = 1;
NSLog(#"1");
}
if ([[array objectAtIndex:indexPath.row] isEqual:#"Shopping"]) {
[enjoy setTitle:[array objectAtIndex:indexPath.row]];
enjoy.radInt = 2;
}
if ([[array objectAtIndex:indexPath.row] isEqual:#"Annat"]) {
enjoy.radInt = 3;
}
[self performSegueWithIdentifier:#"main" sender:self];
}
You don't actually need to implement didSelectRowAtIndexPath: if you connect the segue in the storyboard from the cell to the next controller. What you need to implement is prepareForSegue:. Your code should look something like this:
- (void)prepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender
{
NSInteger row = [self.tableView indexPathForSelectedRow].row;
SecondViewController *enjoy = segue.destinationViewController;
if ([[array objectAtIndex:row] isEqual:#"Livsmedel"]) {
[enjoy setTitle:[array objectAtIndex:row]];
enjoy.radInt = 0;
NSLog(#"0");
}
if ([[array objectAtIndex:row] isEqual:#"Restauranger"]) {
[enjoy setTitle:[array objectAtIndex:row]];
enjoy.radInt = 1;
NSLog(#"1");
}
if ([[array objectAtIndex:row] isEqual:#"Shopping"]) {
[enjoy setTitle:[array objectAtIndex:row]];
enjoy.radInt = 2;
}
if ([[array objectAtIndex:row] isEqual:#"Annat"]) {
enjoy.radInt = 3;
}
}

Plist Search of Tableview

I have Plist which is been populated on the tableview with expanded sections ..now i want to search the table..below in images you can see what is happening when I search anything.
.
just because I am searching it but need some changes in the cellforrowatindexpath for search results....
please check the code and let me know what to do for searching plist..
what should be changes for the cellforrowatindexpath and noofrowsinsection for search from plist
.
.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.mySections count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = 0;
if ([self tableView:tableView canCollapseSection:section] || !(tableView == self.searchDisplayController.searchResultsTableView) )
{
if ([expandedSections containsIndex:section] )
{
NSString *key = [self.mySections objectAtIndex:section];
NSArray *dataInSection = [[self.myData objectForKey:key] objectAtIndex:0];
return [dataInSection count];
}
return 1;
} else if(tableView == self.searchDisplayController.searchResultsTableView) {
rows = [self.searchResults count];
return rows;
}
return 1;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection: (NSInteger)section {
NSString *key = [self.mySections objectAtIndex:section];
return [NSString stringWithFormat:#"%#", key];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//some changes required to display plst
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] ;
}
// Configure the cell...
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]) {
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
}else {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [self.mySections objectAtIndex:section];
NSDictionary *dataForSection = [[self.myData objectForKey:key] objectAtIndex:0];
NSArray *array=dataForSection.allKeys;
cell.textLabel.text = [[dataForSection allKeys] objectAtIndex:row];
cell.detailTextLabel.text=[dataForSection valueForKey:[array objectAtIndex:indexPath.row]];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
if (!indexPath.row)
{
// only first row toggles exapand/collapse
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded)
{
rows = [self tableView:tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
}
else
{
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
}
for (int i=1; i<rows; i++)
{
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i
inSection:section];
[tmpArray addObject:tmpIndexPath];
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (currentlyExpanded)
{
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeDown];
}
else
{
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeUp];
}
}
}
}
- (void)filterContentForSearchText:(NSString*)searchText
scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
self.searchResults = [self.mySections filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
UISearchBar * searchBar = [controller searchBar];
[self filterContentForSearchText:searchString scope:[[searchBar scopeButtonTitles] objectAtIndex:[searchBar selectedScopeButtonIndex]]];
return YES;
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
UISearchBar * searchBar = [controller searchBar];
[self filterContentForSearchText:[searchBar text] scope:[[searchBar scopeButtonTitles] objectAtIndex:searchOption]];
return YES;
}
The search results you are using in numberOfRows should be used for numberOfSections
Since you are filtering for section title and not rows.

accessory checkmark, one at a time in a uitableview-iphone

HI,
how to implement checkmark, one at a time in a uitableview.and then how to save that state in my application? please guide.
right now i am having a table and the data in table row is coming from a nsmutablearray.My .m file is as:
#import "LocationSelection.h"
#implementation LocationSelection
#synthesize menuList, table;
- (void)viewDidLoad {
menuList=[[NSMutableArray alloc] initWithObjects:
[NSArray arrayWithObjects:#"LOCATION1",nil],
[NSArray arrayWithObjects:#"LOCATION2",nil],
[NSArray arrayWithObjects:#"LOCATION3",nil],
[NSArray arrayWithObjects:#"LOCATION4",nil],
[NSArray arrayWithObjects:#"LOCATION5",nil],
[NSArray arrayWithObjects:#"LOCATION6",nil],
[NSArray arrayWithObjects:#"LOCATION7",nil],
nil];
[self.navigationController setNavigationBarHidden:NO];
self.navigationController.navigationBar.tintColor=[UIColor blackColor];
self.navigationController.navigationBar.barStyle=UIBarStyleBlackTranslucent;
self.title=#"Location Selection";
[table reloadData];
[super viewDidLoad];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView{
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 40;
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section{
return menuList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease];
}
cell.highlighted=NO;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
NSArray *rowArray = [menuList objectAtIndex:indexPath.row];
UILabel *nameLabel = [[[UILabel alloc] initWithFrame:CGRectMake(15, 8, 200, 20)]autorelease];
nameLabel.text = [NSString stringWithFormat:#"%#",[rowArray objectAtIndex:0]];
nameLabel.backgroundColor = [UIColor clearColor];
nameLabel.shadowColor=[UIColor whiteColor];
nameLabel.shadowOffset=CGSizeMake(0.0, 0.5);
nameLabel.textColor = RGB(0,0,0);
[nameLabel setFont:[UIFont boldSystemFontOfSize:16.0f]];
[cell.contentView addSubview:nameLabel];
return cell;
}
Thanks!
Comment this line in cellForRowAtIndexPath -> cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
Use this:
NSIndexPath* lastIndexPath; // This as an ivar
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* newCell = [tableView cellForRowAtIndexPath:indexPath];
int newRow = [indexPath row];
int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
if(newRow != oldRow)
{
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell* oldCell = [tableView cellForRowAtIndexPath:lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
lastIndexPath = indexPath;
}
}
In your MenuList you should stock NSDictionaries having 2 keys:
location
visited (if the location should have the checkmark)
NSDictionary *loc = [[NSDictionary alloc] initWithObjectsAndKeys
#"Location 1", #"location",
#"NO", #"visited", nil, nil];
When setting up the cell you would test to see if the "visited" key has a value:
if ([[menuList objectAtIndex: indexPath.row] valueForKey:#"visited"]){
// the location was visited
// setup the checkmark
}
Lastly, to fill in the name of the location, instead of:
nameLabel.text = [NSString stringWithFormat:#"%#",[rowArray objectAtIndex:0]];
put
nameLabel.text = [[rowArray objectAtIndex:0] valueForKey:#"location"];
Hope this helps
Use
cell.accessoryType = UITableViewCellAccessoryCheckmark;
Instead of
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
in your code ...

Set switch to On, reload table then insert a new row

I've got an UITableViewController that I use to create settings of my application.
There is a section with only one row where I put an UISwitch.
How can I insert a new row inside the same section of row with the switch only if the switch in set to YES? And how can I delete this row if the switch is set to NO?
Can anyone help me? Thanks!
I tried to use insertRowsAtIndexPaths:withRowAnimation: method but doesn't work...
This is my settings table code:
- (void)viewDidLoad {
[super viewDidLoad];
self.title = NSLocalizedString(#"Impostazioni", #"");
}
- (void)viewWillAppear:(BOOL)animated {
[self.tableView reloadData];
}
-(void)addCellToSetCode:(id)sender {
if ([codeSwitch isOn]) {
NSIndexPath *updatedIndexPath = [NSIndexPath indexPathForRow:1 inSection:2];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:updatedIndexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
[[NSUserDefaults standardUserDefaults] setBool:codeSwitch.on forKey:#"stateOfSwitch"];
}
else {
NSIndexPath *updatedIndexPath = [NSIndexPath indexPathForRow:1 inSection:2];
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:updatedIndexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
[[NSUserDefaults standardUserDefaults] setBool:codeSwitch.on forKey:#"stateOfSwitch"];
}
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 4;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0) {
return NSLocalizedString(#"ListaDesideri", #"");
}
if (section == 1) {
return NSLocalizedString(#"CondivisioneMail", #"");
}
if (section == 2) {
return #"Sicurezza";
}
else {
return nil;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) || (section == 2) || (section == 3) {
return 2;
}
else if (section == 1) {
return 1;
}
else {
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.section == 0 && indexPath.row == 0) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
cell.textLabel.text = NSLocalizedString(#"Ordine", #"");
if ([[defaults objectForKey:#"ordinaPer"] isEqualToString:#"Nome"]) {
cell.detailTextLabel.text = NSLocalizedString(#"Nome", #"");
}
if ([[defaults objectForKey:#"ordinaPer"] isEqualToString:#"Costo"]) {
cell.detailTextLabel.text = NSLocalizedString(#"Costo", #"");
}
if ([[defaults objectForKey:#"ordinaPer"] isEqualToString:#"Categoria"]) {
cell.detailTextLabel.text = NSLocalizedString(#"Categoria", #"");
}
if ([[defaults objectForKey:#"ordinaPer"] isEqualToString:#"Nome Discendente"]) {
cell.detailTextLabel.text = NSLocalizedString(#"NomeDiscendente", #"");
}
if ([[defaults objectForKey:#"ordinaPer"] isEqualToString:#"Costo Discendente"]) {
cell.detailTextLabel.text = NSLocalizedString(#"CostoDiscendente", #"");
}
if ([[defaults objectForKey:#"ordinaPer"] isEqualToString:#"Categoria Discndente"]) {
cell.detailTextLabel.text = NSLocalizedString(#"CategoriaDiscendente", #"");
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (indexPath.section == 0 && indexPath.row == 1) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
cell.textLabel.text = NSLocalizedString(#"DettagliDesiderio", #"");
if ([[defaults objectForKey:#"dettagliView"] isEqualToString:#"costoView"]) {
cell.detailTextLabel.text = NSLocalizedString(#"Costo", #"");
}
if ([[defaults objectForKey:#"dettagliView"] isEqualToString:#"descrizioneView"]) {
cell.detailTextLabel.text = NSLocalizedString(#"Descrizione", #"");
}
if ([[defaults objectForKey:#"dettagliView"] isEqualToString:#"urlView"]) {
cell.detailTextLabel.text = NSLocalizedString(#"URL", #"");
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (indexPath.section == 1 && indexPath.row == 0) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
cell.textLabel.text = NSLocalizedString(#"Shortener", #"");
if ([[defaults objectForKey:#"linkShortener"] isEqualToString:#"Nessuno"]) {
cell.detailTextLabel.text = NSLocalizedString(#"Nessuno", #"");
}
if ([[defaults objectForKey:#"linkShortener"] isEqualToString:#"is.gd"]) {
cell.detailTextLabel.text = NSLocalizedString(#"is.gd", #"");
}
if ([[defaults objectForKey:#"linkShortener"] isEqualToString:#"bit.ly"]) {
cell.detailTextLabel.text = NSLocalizedString(#"bit.ly", #"");
}
if ([[defaults objectForKey:#"linkShortener"] isEqualToString:#"TinyURL"]) {
cell.detailTextLabel.text = NSLocalizedString(#"TinyURL", #"");
}
if ([[defaults objectForKey:#"linkShortener"] isEqualToString:#"Linkyy"]) {
cell.detailTextLabel.text = NSLocalizedString(#"Linkyy", #"");
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (indexPath.section == 2 && indexPath.row == 0) {
cell.textLabel.text = #"Access Code";
codeSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 84, 27)];
cell.accessoryView = codeSwitch;
[codeSwitch addTarget:self action:#selector(addCellToSetCode:) forControlEvents:UIControlEventValueChanged];
codeSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"codeSwitchState"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
if (indexPath.section == 3 && indexPath.row == 0) {
cell.textLabel.text = NSLocalizedString(#"Supporto", #"");
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (indexPath.section == 3 && indexPath.row == 1) {
cell.textLabel.text = NSLocalizedString(#"Informazioni", #"");
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
EDIT: Updates below...
I solved part of this problem!
I tried to use [self.tableView reloadData] but doesn't work and casually I solved using [self.tableView setNeedsDisplay]...
Now the switch works but if I set to On it and then I go out from app, completely closing it, the switch doesn't work... How can I solve this?
If this can help other, these are pieces of code updated:
-(void)addCellToSetCode:(id)sender {
if ([codeSwitch isOn]) {
NSIndexPath *updatedIndexPath = [NSIndexPath indexPathForRow:1 inSection:2];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:updatedIndexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
[self.tableView setNeedsDisplay];
[[NSUserDefaults standardUserDefaults] setBool:codeSwitch.on forKey:#"codeSwitchState"];
}
else {
NSIndexPath *updatedIndexPath = [NSIndexPath indexPathForRow:1 inSection:2];
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:updatedIndexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
[self.tableView setNeedsDisplay];
[[NSUserDefaults standardUserDefaults] setBool:codeSwitch.on forKey:#"codeSwitchState"];
}
}
// tableView:numberOfRowsInSection:
else if (section == 2) {
return codeSwitch.on ? 2 : 1;
}
// tableView:cellForRowAtIndexPath:
if (indexPath.section == 2 && indexPath.row == 0) {
cell.textLabel.text = #"Access Code";
codeSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 84, 27)];
cell.accessoryView = codeSwitch;
[codeSwitch addTarget:self action:#selector(addCellToSetCode:) forControlEvents:UIControlEventValueChanged];
codeSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"codeSwitchState"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
if (indexPath.section == 2 && indexPath.row == 1) {
if ([codeSwitch isOn]) {
cell.textLabel.text = #"Set Access Code";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
At least part of your problem (in the updated code) is that you don't create the UISwitch until you create the cell. Your codeSwitch ivar may end up pointing to a different switch as that table row comes in and out of view.
Here's how I'd do this: in tableView:numberOfRowsInSection:, use the NSUserDefaults to see which state the table should be in, instead of using the state of the switch (which may not exist yet). Then, in the switch's action method, call setBool:forKey: for the user defaults before you insert or delete the table row.
In essence, this makes the code follow the MVC model better, because it separates your view (the UISwitch) from the model (the BOOL in user defaults), with the controller (the view controller) in the middle. By confounding the view and the model (the switch and the boolean state), you end up with problems when trying to deal with the state when the view isn't available yet.
BTW, you shouldn't need to call setNeedsDisplay on the table view at all.

My tableView only refresh from the UISearchBar only after an additional character is added

I have a tableView that refreshes with data from an array via the textDidChange function for UISearchBar. The data is correct, but it does not appear in the tableView until after hitting an additional character (so, for instance, if i typed 'Boise' into the search bar, nothing happens, but 'Boise1' will load two cities named 'Boise'..so it's one step behind).
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
//---if there is something to search for---
if ([searchText length] > 0) {
NSLog(#"greater than 0!");
isSearchOn = YES;
canSelectRow = YES;
self.tableView.scrollEnabled = YES;
[self performSelector:#selector(someMethod) withObject:nil afterDelay:0];
//[NSThread detachNewThreadSelector:#selector(matchSearchText)
// toTarget:self withObject:nil];
//[self matchSearchText];
}
else {
//---nothing to search---
isSearchOn = NO;
canSelectRow = NO;
self.tableView.scrollEnabled = NO;
}
}
and in the method that is called:
- (void) someMethod {
NSLog(#"-------------");
NSLog(#"some Method whut!");
CityLookup *cityLookup = [[CityLookup alloc] findCity:searchBar.text];
// clear array
[tableCities removeAllObjects];
if ([cityLookup.citiesList count] > 0) {
tableCities = cityLookup.citiesList;
int size = [tableCities count];
NSLog(#"there are %d objects in the array", size);
}
[cityLookup release];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:tableCities waitUntilDone:YES];
}
and finally the cellForRowAtIndexPath:
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
int size = [tableCities count];
NSLog(#"there are %d objects in the array NOW", size);
static NSString *kCellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSString *cellValue = [tableCities objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}