0

UITableView「HomeViewController」というビューを更新して、追加した新しいオブジェクトを表示しようとしています。しかし、NSFetchedResultsController新しいものを作成した後、更新されません。さまざまなドキュメントに次のコードがあります。

HomeViewController.h

- (void)saveNewShindyToDatabaseForName:(NSString *)name
                               details:(NSString *)details
                           dateAndTime:(NSDate *)dateAndTime
                              location:(CLLocation *)location
                            timePosted:(NSDate *)postedTime
{

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

    dispatch_queue_t saveQ = dispatch_queue_create("Shindy Creator", nil);
    dispatch_async(saveQ, ^{
        [self.shindysDatabase.managedObjectContext performBlock:^{
            [Shindy setupShindyForSaveToDatabaseForName:name
                                                details:details
                                            dateAndTime:dateAndTime
                                               location:location
                                             timePosted:postedTime
                                 inManagedObjectcontext:self.shindysDatabase.managedObjectContext];
        }];
    });

    NSError *error = nil;
    if (![self.shindysDatabase.managedObjectContext save:&error]) {
        NSLog(@"%@", error.userInfo);
    }
}

- (void)setupFetchedResultsController
{
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"];
    NSSortDescriptor *nameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    NSSortDescriptor *photoSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"photo" ascending:YES];
    NSSortDescriptor *detailSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES];
    NSSortDescriptor *dateAndTimeSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"dateAndTime" ascending:YES];
    NSSortDescriptor *timePostedSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"timePosted" ascending:YES];
    request.sortDescriptors = [NSArray arrayWithObjects:nameSortDescriptor, photoSortDescriptor, detailSortDescriptor, dateAndTimeSortDescriptor, timePostedSortDescriptor, nil];

    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                        managedObjectContext:self.shindysDatabase.managedObjectContext
                                                                          sectionNameKeyPath:nil
                                                                                   cacheName:nil];
}

Shindy+SQL.m (NSManagedObjectエンティティ「Shindy」のサブクラス)

+ (Shindy *)setupShindyForSaveToDatabaseForName:(NSString *)name
                               details:(NSString *)details
                           dateAndTime:(NSDate *)dateAndTime
                              location:(CLLocation *)location
                            timePosted:(NSDate *)postedTime
                inManagedObjectcontext:(NSManagedObjectContext *)context
{
    Shindy *shindy = [NSEntityDescription insertNewObjectForEntityForName:@"Shindy" inManagedObjectContext:context];

    __block NSString *nameString = name;
    __block FBProfilePictureView *profileImage = nil;

    if (FBSession.activeSession.isOpen) {
        [[FBRequest requestForMe] startWithCompletionHandler:
         ^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
             if (!error) {
                 nameString = user.name;
                 profileImage.profileID = user.id;
             }
         }];
    }

    NSData *imageData = nil;

    for (NSObject *obj in [profileImage subviews]) {
        if ([obj isMemberOfClass:[UIImageView class]]) {
            UIImageView *objImg = (UIImageView *)obj;
            imageData = UIImagePNGRepresentation(objImg.image);;
            break;
        }
    }

    shindy.name = name;
    shindy.dateAndTime = dateAndTime;
    shindy.timePosted = postedTime;
    shindy.details = details;
    shindy.photo = imageData;

    return shindy;
}

メソッド- (void)setupFetchedResultsController:は、ビューが最初に読み込まれるときに呼び出されます (ただし、viewDidLoadorviewWillAppearメソッドでは呼び出されません)。- (void)saveNewShindyToDatabaseForName:ユーザーがデータの入力を完了すると、私の関数は別のView Controllerで呼び出されます。つまり、これは公開 API ですが、 for 委任NSManagedObjectContext内に残ります。HomeViewControllerまた、コードのデリゲートとデータ ソースが適切に設定されています。

私はあらゆる種類のフェッチを強制しようとしました。managedObjectContext 経由か、fetchedResultsController 経由か。NSLogまた、データが確実に に到達するように、コードのさまざまな場所に を設定しましたHomeViewController。またNSLog、fetchedResultsController と managedObjectContext の両方がnil.

すべてがチェックアウトされているようで、現在コード内にある他のデフォルト エラーからのエラーは発生しません。

NSSortDescriptorこれが私のメソッドにある s で何かをしなければならないのではないかと心配してい- (void)setupFetchedResultsController:ますが、さまざまな方法でそれらを構成しようとしても役に立ちませんでした。私の managedObjectContext と私の fetchedResultsController にも明確な接続があるので、それは問題ではありません。

私は単に試してみることを使い果たしました。おそらく、ここにいる誰かが何らかの洞察を持っています。

ジャータートンの場合...

- (void)saveNewShindyToDatabaseForName:最初にそこにあったすべてのコードの後に​​、メソッドに次のコードを実装しました。次のようになります。

- (void)saveNewShindyToDatabaseForName:(NSString *)name
                               details:(NSString *)details
                           dateAndTime:(NSDate *)dateAndTime
                              location:(CLLocation *)location
                            timePosted:(NSDate *)postedTime
{
    // All of the code originally in this method is here...

    if ([self.fetchedResultsController managedObjectContext] == self.shindysDatabase.managedObjectContext) {
        NSLog(@"MOC's are the same.");
    }

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"];
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES];
    request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

    NSError *error = nil;
    NSArray *detailsArray = [self.shindysDatabase.managedObjectContext executeFetchRequest:request error:&error];

    if (error) {
        NSLog(@"error: %@", error.userInfo);
    }

    NSLog(@"details: %@", detailsArray);
}

このすべてが返すのは、2 番目の可能な答えに答えるために、MOC は間違いなく同じであるということです。ただし、新しいオブジェクトが実際には Core Data に保存されていないように見えます。または、適切に引き戻していません。

認識できないセレクター エラーを発生させずに Core Data の内容をログに記録する唯一の方法は、正しいエンティティに対する新しい要求を作成し、フェッチを実行して、そのフェッチの結果をログに記録することでした。場合、何も返されませんでした。

私の問題は、新しいオブジェクトを Core Data に保存しないコードにあると仮定します。そうは言っても、これらのオブジェクトをコンテキストに適切に保存していない場所を特定して、後で取得するために Core Data モデルに配置できるようにできますか? または、コア データに保存されているものをログに記録するように要求する以外に、別の方法を設定する必要がありますか?

4

1 に答える 1

2

考えられる問題:

  1. フェッチされた結果コントローラー デリゲートはありません (OK、コメントに従って解決されました)。
  2. FRC は、データベースを作成する前に設定されている可能性があります (最初のメソッド内で新しいデータベースを作成しますが、FRC はその前に設定されていると言います。それらは同じ MOC オブジェクトを持っていますか?
  3. マルチスレッド地獄 - MOC 保存呼び出しは、完了ブロックを渡すメソッドを呼び出すメソッドを呼び出すブロックの前に実行されます (ふー!)。これにより、通知が追いつかない可能性があります。

新しいオブジェクトがデータベースに入るかどうかについては言及していません-アプリを保存して閉じてから再度開いた場合、それらはありますか? 変更通知の送信または受信の失敗、または変更の失敗に対処していますか?

于 2013-01-12T09:30:18.670 に答える