Restkit / CoreData - 更新实体的属性不会更新UITableView

时间:2014-12-17 22:59:13

标签: ios objective-c uitableview core-data restkit

我有一个实体Country,其中包含一个属性downloaded,其默认值为0,并且不由RestKit映射。我希望能够根据下载的属性将tableView分组为多个部分。一切都按预期工作,直到我尝试以编程方式自行更改下载的值。代码如下:

我正在尝试设置值 - 我的上下文是通过AppDelegate传递给控制器​​的mainQueueManagedObjectContext

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    Country *country = [self.fetchedResultsController objectAtIndexPath:indexPath];
    [FGDataCalls downloadFieldGuide:country.countryId];

    //Set up to get the thing you want to update
    NSFetchRequest * request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:@"Country" inManagedObjectContext:self.managedObjectContext]];
    [request setPredicate:[NSPredicate predicateWithFormat:@"countryId = %@", country.countryId]];

    NSError *error = nil;
    country = [[self.managedObjectContext executeFetchRequest:request error:&error] lastObject];

    if (error) {
        NSLog(@"Error getting the country from core data: %@", error);
    }

    country.downloaded = 1;

    error = nil;
    if (![self.managedObjectContext save:&error]) {
        NSLog(@"Saving changes to country failed: %@", error);
    }
}

FetchedResultsController:

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    /*
     Set up the fetched results controller.
     */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Country" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Sort using the name property.
    NSSortDescriptor *sortDownloaded = [[NSSortDescriptor alloc] initWithKey:@"downloaded" ascending:NO];
    NSSortDescriptor *sortName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    [fetchRequest setSortDescriptors:@[sortDownloaded, sortName]];

    // Use the sectionIdentifier property to group into sections.
    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"downloaded" cacheName:nil];
    _fetchedResultsController.delegate = self;
    self.fetchedResultsController = _fetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}

初始化Restkit:

//Enable RestKit logging
//RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelInfo);
//RKLogConfigureByName("RestKit/CoreData", RKLogLevelTrace);
//RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);

// Initialize RestKit
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:BaseURLString]];

// Initialize managed object store
NSError *error = nil;
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"FGDataModel" ofType:@"momd"]];
NSManagedObjectModel *managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];

BOOL success = RKEnsureDirectoryExistsAtPath(RKApplicationDataDirectory(), &error);
if (!success) {
    RKLogError(@"Failed to create Application Data Directory at path '%@': %@", RKApplicationDataDirectory(), error);
}

objectManager.managedObjectStore = managedObjectStore;

NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"FGDataModel.sqlite"];
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];

if (! persistentStore) {
    RKLogError(@"Failed adding persistent store at path '%@': %@", path, error);
}

// Configure a managed object cache to ensure we do not create duplicate objects
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];

[managedObjectStore createManagedObjectContexts];

// Set the default store shared instance
[RKManagedObjectStore setDefaultStore:managedObjectStore];

// Setup our object mappings
[FGDataCalls setupObjectMappings:managedObjectStore withObjectManager:objectManager];

// Save the MOC
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
appDelegate.managedObjectContext = managedObjectStore.mainQueueManagedObjectContext;

我已尝试在此时以多种不同的方式保存上下文,包括块,我还没有让fetchedResultsController识别更新,甚至调用controllerWillChangeContent:controllerDidChangeContent:。我已经使用MOC的deleteObject:方法成功删除了一行,因此我的上下文处于正确的状态。我甚至可以在设置了下载的属性后从我的fetchedResultsController获取对象并查看它是否正确,但表永远不会更新。此外,在我更改属性后强制表重新加载不会产生任何结果。我知道这是一个具体的案例,但希望其他人遇到同样的问题,或者可以看到我出错的地方。

谢谢!

1 个答案:

答案 0 :(得分:0)

保存时不应该

error = nil;
if (![self.managedObjectContext save:&error]) {
    NSLog(@"Saving changes to country failed: %@", error);
}

你应该做

error = nil;
if (![self.managedObjectContext saveToPersistentStore:&error]) {
    NSLog(@"Saving changes to country failed: %@", error);
}

也就是说,假设FRC连接到相同的上下文,那么它应该在保存之前看到更改。您也不会显示您的FRC委托方法,因此可能存在问题。