1

我有一个 CoreData 模型,其中包含可以再次包含 childLevels 的 Levels。

我用UITableViewController列出所有 childLevels 来表示每个级别。当用户点击一行时,一个新UITableViewController的被推送到navigationController. 这里没问题。

我将如何在此表结构中存储用户位置。是否有这样做的最佳实践?如果结构的深度是已知的,我这样做是没有问题的,但不知何故不知道如何以未定义的深度来处理这个问题。

我应该NSIndexPath将用户点击的数据存储到一个数组中并将其写入磁盘吗?

4

3 回答 3

1

我没有使用用户点击的 NSIndexPaths,而是使用了底层的 NSManagedObjects,它更安全(以防对象的数量或排序发生变化)和更快(因为我不需要整个 fetchRequest 和/或视图)。

我将 UINavigationController 子类化并执行了以下操作。

当为一个级别(存储在parentLevel)推送一个新的 TableViewController 时,我将它附加到 UserDefaults 中的一个数组中:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
   [super pushViewController:viewController animated:animated];

   if([viewController isKindOfClass:[LevelTableViewController class]]){
       NSMutableArray *array = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:LevelTablesPersistentKey]];
       NSManagedObject *obj = [(LevelTableViewController*)viewController parentLevel];

       if(obj!=nil){
         [array addObject:[[obj objectID].URIRepresentation absoluteString]];
       } 

       [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:array] objectForKey:LevelTablesPersistentKey];

   }
}

当我弹出一个 viewController 时,我只需从该数组中删除最后一个条目:

- (UIViewController *) popViewControllerAnimated:(BOOL)animated{
  UIViewController *vc = [super popViewControllerAnimated:animated];
  // remove last object
  if([vc isKindOfClass:[LevelTableViewController class]]){
     NSMutableArray *array = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:LevelTablesPersistentKey]];
     [array removeLastObject];
     [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:array] objectForKey:LevelTablesPersistentKey];
  }

  return vc;
}

然后,当应用程序下一次开始重建树时,我可以在初始化 NavigationController 时使用此数组:

- (LevelNavigationController*) initWithRootViewController:(LevelTableViewController*)vc {
if(self = [super initWithRootViewController:vc]){
    // Recreate structure from UserDefaults
    NSArray *array = [NSArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:LevelTablesPersistentKey]];
    [[NSUserDefaults standardUserDefaults] setObject:nil forKey:LevelTablesPersistentKey]; // set the array to nil -> will be rebuild when pushing viewcontrollers onto navigation stack

    NSPersistentStoreCoordinator *persistentStoreCoordinator = ...; // pointer to coordinator 
            NSManagedObjectContext * managedObjectContext = ...; // pointer to your context
    for (NSString *objId in array) {
        NSManagedObjectID *mobjId=[persistentStoreCoordinator managedObjectIDForURIRepresentation:[NSURL URLWithString:objId]];
        if(mobjId!=nil){

            NSManagedObject *obj = nil;
            NSError **err = nil;
            obj = [managedObjectContext objectWithID:mobjId];

            if(err==nil && obj){
                if([obj.entity.name isEqualToString:@"Level"]){
                    // push level

                    LevelTableViewController *nextLevel = [[LevelTableViewController alloc] initWithStyle:UITableViewStylePlain];
                    nextLevel.parentLevel = (Level*)obj;
                    [self pushViewController:nextLevel animated:NO];
                    [nextLevel release];
                } 
            } 
        }
    }

}

return self;

}
于 2010-02-05T13:46:43.180 回答
1

为您的状态使用NSIndexPath并保存/恢复它以保持持久性对我来说很有意义。

此外,您的方法——使用存储为属性列表(plist)的 NSArray——应该相当简单。

于 2010-02-04T21:40:37.310 回答
0

我正准备开始为我自己的应用程序执行此操作,这是计划。每次 UIViewController 加载一个新视图时,它都会在 NSUserDefaults 中创建一个值,该值提供有关该新视图的信息(从何处打开、填充了哪些数据等)。当子视图返回时,视图控制器清除该值。当 UIViewController 有它的初始加载时,它会检查默认值以查看它之前是否存储了一个值,如果是,它会采取适当的操作来重新加载该子视图。该过程沿导航链向下继续。

我这样做而不是 NSIndexPath 的原因是,除了主视图层次结构之外,我还有一堆辅助视图(添加、删除、编辑等)。我不仅需要记录这些视图的打开情况,这些视图存在于主导航之外,而且它们还有很多需要保存的状态细节(选定的选项、部分输入的文本等)

如果结果证明这是一个糟糕的计划,我会回到这里并对此投反对票。

于 2010-02-04T22:00:10.837 回答