I am in the process of writing a Master/Detail CoreData RSS reader for the fun of it.
I use the following entities:
Category 1->n Feed 0->n Post
So in the left Pane of my UISplitView, there are the Feeds grouped by Category. Choosing a Feed will fetch, then display its Posts in the right pane.
The right pane also contains a UITableView which uses 2 sorts of prototype cells:
read
and unread
.
read
and unread
depends upon the property (NSDate *)read
of the corresponding Post
ManagedObject: if it's nil
, then it's to be displayed using an unread
prototype cell.
Here's the code for the cellForRowAtIndexPath
method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *feedTableIdentifier = @"unread";
Post *thepost = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSDate *tmpDate=[NSDate date];
if (thepost.read) {
tmpDate=thepost.read;
feedTableIdentifier = @"read";
} else if (thepost.date) {
tmpDate=thepost.date;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:feedTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:feedTableIdentifier];
}
((UILabel *)[cell viewWithTag:1]).text = thepost.title;
NSDateFormatter *df=[[NSDateFormatter alloc] init];
df.dateFormat = @"EEEE, MMMM d, YYYY";
((UILabel *)[cell viewWithTag:2]).text = [df stringFromDate:tmpDate];
((UILabel *)[cell viewWithTag:3]).text = [self flattenHTML:thepost.excerpt];
return cell;
}
Now, whenever I select a Post cell, I follow a segue which push a WebView pane onto the right pane. This WebView shows the contents of the relevant Post.url
page.
In the same time, I will edit the current Managed Object read
property which I will set to the current NSDate.
I will then save the ManagedObjectContext and refetch the right pane's Feeds to reflect the new format:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
PostDetailController *webController = [[PostDetailController alloc] init];
if ([[segue identifier] isEqualToString:@"ShowWebLink"]) {
webController = [segue destinationViewController];
webController.urlstr = ((Post *)sender).url;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Post *post=[self.fetchedResultsController objectAtIndexPath:indexPath];
[self performSegueWithIdentifier:@"ShowWebLink" sender:post];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
post.read = [NSDate date];
NSError *error;
if (![self.managedObjectContext save:&error])
{
NSLog(@"[didSelectRowAtIndexPath] Error saving context: %@", error);
}
[self refetch];
}
Now, here's my problem:
When I pop the UIWebView and come back to the Feed list, the taped Post cell and all the following cells are now displayed as read
the first time.
The second time, all the cells in the UITableView are shown as read
.
Could anybody tell me what I am doing wrong here? I would like only the selected object to be marked as read...
Thanks in advance for your help.
EDIT:
Could it come from this line in the didSelectRowAtIndexPath
method?
post.read = [NSDate date];
Should I replace it with:
[post setValue:[NSDate date] forKey:@"read”];
I am still confused by the dot notation vs setValue
...
EDIT 2:
Nope :( Just did the test.
Solved.
The other data were not modified. I changed the cellForRowAtIndexPath
method the following way:
WAS
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *feedTableIdentifier = @"unread";
Post *thepost = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSDate *tmpDate=[NSDate date];
if (thepost.read) {
tmpDate=thepost.read;
feedTableIdentifier = @"read";
} else if (thepost.date) {
tmpDate=thepost.date;
}
IS
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *feedTableIdentifier = @"unread";
Post *thepost = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSDate *tmpDate=[NSDate date];
if (thepost.read) {
tmpDate=thepost.read;
feedTableIdentifier = @"read";
} else if (thepost.date) {
tmpDate=thepost.date;
feedTableIdentifier = @"unread";
}
The static
variable was affecting the other rows...