1

我有一个NSFetchedResultsController,我已经确认每当用户创建一个新对象时,他们的数据就会被保存到其中。但是,我发现唯一没有更新的是NSFetchedResultsController. 我不确定为什么会这样。

我尝试以多种不同的方式改变新对象的创建。我还尝试记录该过程的每个步骤以尝试查看发生了什么,但是我真的没有多少可以记录这样的事情,所以我现在几乎没有关于为什么会发生这种情况的信息. 无论如何,这里是代码:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSLog(@"number of sections: %d", [[self.fetchedResultsController sections] count]);
    return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSLog(@"number of rows: %d", [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects]);
    return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}

- (void)saveForName:(NSString *)name
              photo:(NSData *)photo
         timePosted:(NSDate *)timePosted
            details:(NSString *)details
        dateAndTime:(NSDate *)dateTime
           location:(NSString *)location
{

    if (!self.shindysDatabase) {
        NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        self.shindysDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
        NSLog(@"shindy database reset.");
    }

    Shindy *shindy = (Shindy *)[NSEntityDescription insertNewObjectForEntityForName:@"Shindy" inManagedObjectContext:self.shindysDatabase.managedObjectContext];

    shindy.name = name;
    shindy.photo = photo;
    shindy.timePosted = timePosted;
    shindy.details = details;
    shindy.dateAndTime = dateTime;
    shindy.location = location;

    NSError *error = nil;
    [self.shindysDatabase.managedObjectContext save:&error];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    }

    Shindy *shindy = (Shindy *)[NSEntityDescription entityForName:@"Shindy" inManagedObjectContext:self.shindysDatabase.managedObjectContext];
    shindy = [self.fetchedResultsController objectAtIndexPath:indexPath];

    UIImageView *avatar = [[UIImageView alloc] initWithFrame:CGRectMake(20, 10, 64, 56)];
    // Converting NSData to UIImage
    avatar.image = shindy.photo;
    avatar.clipsToBounds = NO;
    [cell addSubview:avatar];

    NSLog(@"avatar: %@", avatar);

    // The name of the user who posted the shindy
    UILabel *avatarName = [[UILabel alloc] initWithFrame:CGRectMake(90, 10, 125, 19)];
    avatarName.font = [UIFont boldSystemFontOfSize:15];
    avatarName.backgroundColor= [UIColor clearColor];
    avatarName.text = shindy.name;
    [cell addSubview:avatarName];

    NSLog(@"avatarName: %@", avatarName);

    // The time the shindy was posted
    NSDateFormatter *timePostedFormatter = [[NSDateFormatter alloc] init];
    [timePostedFormatter setDateFormat:@"mm"];
    UILabel *timePosted = [[UILabel alloc] initWithFrame:CGRectMake(280, 10, 30, 20)];
    timePosted.font = [UIFont systemFontOfSize:12];
    timePosted.textColor = [UIColor lightGrayColor];
    timePosted.backgroundColor= [UIColor clearColor];
    timePosted.text = [timePostedFormatter stringFromDate:shindy.timePosted];
    [cell addSubview:timePosted];

    NSLog(@"Time posted: %@", timePosted);

    // Formatting fetched NSDate into string
    NSDateFormatter *dateAndTimeFormatter = [[NSDateFormatter alloc] init];
    [timePostedFormatter setDateFormat:@"MM/DD/YYYY hh:mm"];
    UILabel *dateAndTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(250, 70, 30, 20)];
    dateAndTimeLabel.font = [UIFont systemFontOfSize:12];
    dateAndTimeLabel.backgroundColor= [UIColor clearColor];
    dateAndTimeLabel.text = [dateAndTimeFormatter stringFromDate:shindy.dateAndTime];
    [cell addSubview:dateAndTimeLabel];

    NSLog(@"date and time: %@", dateAndTimeLabel.text);

    // Details of the Shindy
    UILabel *shindyDescription = [[UILabel alloc] initWithFrame:CGRectMake(90, 20, 220 , 50)];
    shindyDescription.numberOfLines = 3;
    shindyDescription.font = [UIFont systemFontOfSize:12];
    shindyDescription.backgroundColor = [UIColor clearColor];
    shindyDescription.text = shindy.details;
    [cell addSubview:shindyDescription];

    NSLog(@"details: %@", shindyDescription.text);

    return cell;
}

样板代码:

这只是我在更改对象时必须进行更新的代码。

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray
                                               arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray
                                               arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    [self.tableView endUpdates];
}
4

2 回答 2

0

我很久没有使用 NSFetchedResultController 了,但乍一看我会说:
Where are you asking your table view to update itself?
我不认为结果控制器会触发表更新本身。


我刚刚在NSFetchedResultsController文档中,我也看到了这个:

此外,获取的结果控制器提供以下功能:
可选地监视关联托管对象上下文中对象的更改,并将结果集中的更改报告给其委托(请参阅“控制器的委托”)。

并且在NSFetchedResultsControllerDelegate文档 中

您可以只实现 controllerDidChangeContent: (在处理完所有待处理的更改后将其发送给委托)以重新加载表视图。


仅出于调试目的,您是否尝试删除:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type

只是做:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView reloadData];
}

我并不是说这是一个解决方案,但看看结果是否相同会很有趣。

于 2013-01-16T02:12:36.583 回答
0

您在创建 NSFetchedResultsController 对象时是否指定了 sectionNameKeyPath?如果使用 nil,则只会创建一个部分。

(instancetype)initWithFetchRequest:(NSFetchRequest *)fetchRequest managedObjectContext:(NSManagedObjectContext *)context sectionNameKeyPath:(NSString *)sectionNameKeyPath cacheName:(NSString *)name;

sectionNameKeyPath:返回部分名称的结果对象的键路径。传递 nil 表示控制器应该生成单个部分。

于 2017-01-26T11:00:27.203 回答