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:函数就会在单独的视图控制器中调用。换句话说,它是公共 API,但NSManagedObjectContext仍保留在HomeViewControllerfor 委托中。此外,我的代码的代表和数据源设置正确。

我试图强制每一种获取;无论是通过 managedObjectContext 还是 fetchedResultsController。我还在NSLog代码的各个位置设置了一个,以确保数据通过HomeViewController. 我还设置了另一个NSLog以确保 fetchedResultsController 和 managedObjectContext 都不是nil

一切似乎都已检查,并且我没有从我的代码中当前的其他默认错误中得到任何类型的错误。

我担心这与NSSortDescriptor我的- (void)setupFetchedResultsController:方法中的 s 有关系,但我也尝试以各种方式配置它们,但无济于事。我的 managedObjectContext 和我的 fetchedResultsController 也有明确的联系,所以这不是问题。

我只是用完了可以尝试的东西。或许,这里有人有一些见识。

对于jrturton...

- (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);
}

所有这些返回的是,要回答您的第二个可能的答案,MOC 肯定是相同的。然而,新对象似乎并没有真正保存到 Core Data 中。或者我没有正确地将它们拉回来。

我能想到的在不出现无法识别的选择器错误的情况下记录我的核心数据内部的唯一方法是为正确的实体创建一个新请求,然后执行一个提取,然后记录该提取的结果,在这个情况下,什么也没返回。

我将假设我的问题在于我的代码没有将新对象保存到 Core Data。话虽如此,您能否识别出我没有将这些对象正确保存到我的上下文中以便可以将其放入我的核心数据模型中以供以后检索的任何地方?或者我是否需要设置不同的方法,而不是请求将保存到我的核心数据中的内容记录下来?

4

1 回答 1

2

可能的问题:

  1. 没有获取结果控制器委托(好的,根据评论解决)。
  2. FRC 可能在您拥有数据库之前设置(您在第一种方法中创建一个新数据库,但说 FRC 是在此之前设置的 - 它们是否具有相同的 MOC 对象?
  3. 多线程地狱 - 您的 MOC 保存调用将在调用方法的块之前执行,该方法调用通过完成块的方法(呸!)。这很可能导致通知无法赶上。

您没有提及新对象是否曾经进入数据库 - 如果您保存、关闭并重新打开应用程序,它们是否存在?我们是在处理无法发送或接收更改通知,还是无法进行更改?

于 2013-01-12T09:30:18.670 回答