Reputation: 4306
I have 2 tableViews, the first one is the Main table and the second one is the Favorites table.
Everything is handled with a plist.
From the detailView of the first table, in the upper-right corner, I created a button that writes to the plist the value YES or NO for that cell, so that that specific cell will be shown in the table Favorites.
Now the problem is that:
I noticed that if i add to favorites the first item of the firstTable, then the other cells in the second view are shown correctly, even after i favorited them all in the first view.
A bit tricky, i know, but it's happening.
Any idea why?
The method i'm using for reading the plist is the following:
- (NSArray*)readPlist
{
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *plistPath = [[documentPaths lastObject] stringByAppendingPathComponent:@"tipsList.plist"];
NSFileManager *fMgr = [NSFileManager defaultManager];
if (![fMgr fileExistsAtPath:plistPath]) {
plistPath = [[NSBundle mainBundle] pathForResource:@"list" ofType:@"plist"];
}
NSMutableArray *returnArr = [NSMutableArray arrayWithContentsOfFile:plistPath];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isFav == YES"];
for (NSDictionary *sect in returnArr) {
NSArray *arr = [sect objectForKey:@"Rows"];
[sect setValue:[arr filteredArrayUsingPredicate:predicate] forKey:@"Rows"];
}
return returnArr;
[self.tableView reloadData];
}
cellForRow:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSArray *rows;
if (tableView == self.searchDisplayController.searchResultsTableView) {
rows = filteredList;
} else {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isFav == YES"];
NSDictionary *section = [localSortedTips objectAtIndex:indexPath.section];
rows = [section objectForKey:@"Rows"];
[rows filteredArrayUsingPredicate:predicate];
}
cell.textLabel.text = [[rows objectAtIndex:indexPath.row] objectForKey:@"name"];
return cell;
}
And the didSelectRow:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{ NSDictionary *section = [localList objectAtIndex:indexPath.section];
NSArray *rows = [section objectForKey:@"Rows"];
NSDictionary *item = [rows objectAtIndex:indexPath.row];
detailViewController *detail = [[detailViewController alloc] initWithNibName:@"detailViewController" bundle:nil];
detail.indexPath = indexPath;
detail.imageString = [item valueForKey:@"image"];
detail.nameString = [item valueForKey:@"name"];
detail.title = [item valueForKey:@"name"];
detail.descriptionString = [item valueForKey:@"description"];
[self.navigationController pushViewController:detail animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[detail release];
}
}
EDIT WITH PICS
Okay so. I select the first row in the first section of the mainTable, and the detailView appears:
Then i favorite it through that little star, setting its value to YES in the plist
Then I go into the Favorites table, clicking on the previously favorited element and it appears like so
OK. This works. but only for this one!
In fact, if i try to select i.e. a row in the middle of the mainTable, and try to favoriting it, the detailView looks like
But then, selecting it in the Favorites table looks like so, empty star, while it should be favorited and then filled. If i try to favorite it through the star, and coming back to the Favorites table, the previous row in the mainTable appears, even if it's not favorited.
I noticed that if i keep the first element, it works fine, but if i remove it, it doesn't work ANYTHING anymore. :\
Any help highly appreciated,stuck from 2 weeks.
Upvotes: 1
Views: 579
Reputation: 483
As per your question, You have two table views. one is main Table and second one is favorite table. If you select the favorite icon in the main table, need to change the key value in plist to YES
and need to reload both the tables. is this right?
if yes, you have to follow the following steps.
are the both table view cells are same? if no, please differentiate it in cellForRowAtIndexPath:.
are you updating the favorite key value in plist? while selecting the favorite button. According to your code it seems to be NO.
once you have updated the plist, need to reload the both (main table & favorite table) the tables. are you reloading the tables? you are not reloading the table in your code because you have written this after return statement.
please check these conditions and let me know if you have any other prospective.
I think this may helpful to you.
Upvotes: 0
Reputation:
The indexPath
you passing to your detailController
in favoritesView
isn't the same like the one in mainView
. So you have to do some magic to parse the filtered indexPath
back to the original unfiltered list.
- (NSArray*)readPlist // still filtered list
{
NSMutableArray *returnArr = [[self readFullPlist] mutableCopy];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isFav == YES"];
for (NSDictionary *sect in returnArr) {
NSArray *arr = [sect objectForKey:@"Rows"];
[sect setValue:[arr filteredArrayUsingPredicate:predicate] forKey:@"Rows"];
}
return returnArr;
}
- (NSArray*)readFullPlist // split that method to get the unfiltered list separately
{
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *plistPath = [[documentPaths lastObject] stringByAppendingPathComponent:@"tipsList.plist"];
NSFileManager *fMgr = [NSFileManager defaultManager];
if (![fMgr fileExistsAtPath:plistPath]) {
NSString *bundlePlistPath = [[NSBundle mainBundle] pathForResource:@"tipsList" ofType:@"plist"];
[self writePlist:[NSArray arrayWithContentsOfFile:bundlePlistPath]];
}
return [NSArray arrayWithContentsOfFile:plistPath];
}
- (NSIndexPath*)realIndexPathForIndex:(NSIndexPath*)idxPath
{
NSArray *fullList = [self readFullPlist];
NSArray *subArr = [[fullList objectAtIndex:idxPath.section] objectForKey:@"Rows"];
int row = idxPath.row;
int newRow = 0;
for (NSDictionary *dic in subArr)
{
if ([[dic valueForKey:@"isFav"] boolValue]) {
if (row == 0) {
return [NSIndexPath indexPathForRow:newRow inSection:idxPath.section];
}
row--;
}
newRow++;
}
return idxPath;
}
Then in didSelectRowAtIndexPath:
you pass this converted indexPath
instead of the old one:
//detail.indexPath = indexPath;
detail.indexPath = [self realIndexPathForIndex:indexPath];
Something I want to mention. Instead of using the indexPath
you should use an unique identifier if possible. This would make things (like this one) much easier because you only pass that id
to the next controller.
Upvotes: 2
Reputation: 6172
No were in your readPlist method do you say which isFav to read. So even though all rows/cells have their own entries in the plist you are not getting the specific isFav for that specific row
Upvotes: 0
Reputation: 6803
I've had problems with things like this with custom table cells. Usually the problem is in the cellForRowAtIndexPath method. Because you say it gives you the first cell back, I would guess that you're reusing your cells. It doesn't matter which one you tell it to load, if you're reusing cells xcode will just throw the first cell in that it thinks is suitable. Here's how to get rid of the problem:
//Returns a cell to be used at a row, populates it from the holder object
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *tempPlist = [self readPlist];
static NSString *CellIdentifier = @"Cell";
[tableView registerNib:nib forCellReuseIdentifier:CellIdentifier];
UITableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.favorite = [tempPlist objectAtIndex:indexPath.row];
return cell;
}
Upvotes: 0