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 に答える