RESTKit:NSFetchedResultsController在重新创建managedObjectStore后不会填充tableView

时间:2014-06-14 12:29:53

标签: uitableview core-data restkit-0.20 nsfetchedresultscontroller

我以编程方式构建我的TabBar,并根据用户是否登录,我设置 [self.window setRootViewController:home];

以下是我调用的代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

if (![Persistence loggedIn])
{
    [self showLoginScreen];
}
else
{        
    SignupBase *login = [STLoginSignupBase new];
    [login loginUserwithUsername:[Persistence username] andPassword:[Persistence authPass] requestByNewUser:NO completionBlock:^(NSError *error)
    {            
        if (!error)
        {
            [login loginSuccess];
            [self showTabBarScreen];
        }
        else
        {
            [STAlertViewUtils showAlert:@"" :error.localizedDescription :kButtonTitleDismiss];
            [self showLoginScreen];
        }
    }];
}


-(void)showTabBarScreen
{
    dispatch_async(dispatch_get_main_queue(), ^{
        TabBarVC *tabBarVC = [[TabBarVC alloc]init];
        [self.window setRootViewController:tabBarVC];
    });
}

-(void)showLoginScreen
{
    dispatch_async(dispatch_get_main_queue(), ^{
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"STLoginSignup" bundle:nil];
        HomeVC *homeVC = (HomeVC *)[storyboard instantiateViewControllerWithIdentifier:[HomeVC storyboardID]];
        UINavigationController *home = [[UINavigationController alloc]initWithRootViewController:homeVC];
        [self.window setRootViewController:home];
    });

}

TabBar,第一个标签"收件箱"是一个使用NSFetchedResultsController管理的tableViewController。当我第一次启动应用程序时,所有对象都被提取并在tableView中显示得很漂亮;但是,当我退出并重新登录时,"收件箱"重新加载,我得到一个空白的tableView。零对象在本地获取,即使RESTkit提取对象,它们也不会出现在tableView中。当我在模拟器中停止应用程序并重新启动它时,所有对象都在本地和远程获取,并在应该出现在tableView中!

以下是我从Profile标签(不同标签)注销的方式:

- (void)logoutWithCompletionBlock:(void(^)(void))completionBlock
{
    [Persistence setLoggedInStatus:NO];

    RKObjectManager *objectManager = [self getObjectManager];
    [objectManager.HTTPClient clearAuthorizationHeader];

    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *managedObjectContext = delegate.managedObjectStore.mainQueueManagedObjectContext;
    [managedObjectContext reset];
    [delegate deregisterWithUrbanAirship];

    if (completionBlock)
    {
        completionBlock();
    }
}

在我重新登录应用程序后,"收件箱"选项卡viewController再次加载。

在我的"收件箱"调用loadView,我有以下代码:

- (void)loadView
{
    [self getManagedObjectFromAppDelegate]
}

- (void)getManagedObjectFromAppDelegate
{
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    [appDelegate setupCoreDataWithRESTKit];
    self.objectManager = [self getObjectManager];

    self.objectManager.managedObjectStore = appDelegate.managedObjectStore;
    self.objectManager.managedObjectStore.managedObjectCache = appDelegate.managedObjectStore.managedObjectCache;
    self.managedObjectContext = self.objectManager.managedObjectStore.mainQueueManagedObjectContext;
}

这是[AppDelegate setupCoreDataWithRESTKit];

中的代码
- (RKManagedObjectStore *)setupCoreDataWithRESTKit
{

    NSError * error;
    NSURL * modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"App" ofType:@"momd"]];
    NSManagedObjectModel * managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
    self.managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];

    [self.managedObjectStore createPersistentStoreCoordinator];

    NSArray * searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString * documentPath = [searchPaths objectAtIndex:0];
    NSPersistentStore * persistentStore = [self.managedObjectStore addSQLitePersistentStoreAtPath:[NSString stringWithFormat:@"%@/App%@.sqlite", documentPath, [Persistence username]] fromSeedDatabaseAtPath:nil withConfiguration:nil options:[self optionsForSqliteStore] error:&error];
    NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error);

    NSLog(@"Path: %@", [NSString stringWithFormat:@"%@/App%@.sqlite", documentPath, [Persistence username]]);

    if(!persistentStore){
        NSLog(@"Failed to add persistent store: %@", error);
    }

    [self.managedObjectStore createManagedObjectContexts];

    return self.managedObjectStore;

}

请注意,每个用户都根据用户名加载了不同的.sqlite文件:即AppUserName。因此,当我注销并重新登录时,如果它是同一个用户,则创建/加载相同的文件。如果它是不同的用户,则创建/加载不同的名称文件。

问题:为什么在我退出并重新登录后NSFetchedResultsController显示一个空的tableView,但是当我第一次启动应用程序时它可以正常工作?

*编辑*

我改变并尝试了下面的代码,但问题仍然存在:

- (void)logoutWithCompletionBlock:(void(^)(void))completionBlock
{
    [Persistence setLoggedInStatus:NO];

    RKObjectManager *objectManager = [self getObjectManager];
    [objectManager.HTTPClient clearAuthorizationHeader];

    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *managedObjectContext = delegate.managedObjectStore.mainQueueManagedObjectContext;
    [self clearManagedObjectContext:managedObjectContext];
    [delegate deregisterWithUrbanAirship];

    if (completionBlock)
    {
        completionBlock();
    }
}

- (void)clearManagedObjectContext:(NSManagedObjectContext*)managedObjectContext
{
    NSFetchRequest * fetch = [[NSFetchRequest alloc] init];
    [fetch setEntity:[NSEntityDescription entityForName:@"EntityA" inManagedObjectContext:managedObjectContext]];
    NSMutableArray *result = [NSMutableArray arrayWithArray:[managedObjectContext executeFetchRequest:fetch error:nil]];
    for (id entityA in result)
    {
        [managedObjectContext deleteObject:entityA];
    }
    [result removeAllObjects];

    [fetch setEntity:[NSEntityDescription entityForName:@"EntityB" inManagedObjectContext:managedObjectContext]];
    result = [NSMutableArray arrayWithArray:[managedObjectContext executeFetchRequest:fetch error:nil]];
    for (id entityB in result)
    {
        [managedObjectContext deleteObject:entityB];
    }
    [result removeAllObjects];


    [fetch setEntity:[NSEntityDescription entityForName:@"EntityC" inManagedObjectContext:managedObjectContext]];
    result = [NSMutableArray arrayWithArray:[managedObjectContext executeFetchRequest:fetch error:nil]];
    for (id entityC in result)
    {
        [managedObjectContext deleteObject:entityC];
    }
    [result removeAllObjects];


    [managedObjectContext saveToPersistentStore:nil];
}

1 个答案:

答案 0 :(得分:1)

除非您拆除支持主线程上下文的持久存储(因此,拆除整个Core Data堆栈并销毁SQLite文件),否则不应该执行[managedObjectContext reset];

要么纠正这个问题,要么只是在上下文中循环删除要删除的内容,并将更改保存到(父)持久化上下文中。