在UISplitViewController中重用详细的视图控制器

时间:2011-05-11 10:50:46

标签: iphone objective-c ios ipad uisplitviewcontroller

基本上,当我实现像Apple示例'MultipleDetailsViews'中提供的分割视图时,一切正常,它会在每次选择行时分配新的详细视图。以下是示例中的相关代码:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    
    UIViewController <SubstitutableDetailViewController> *detailViewController = nil;

    if (row == 0) {
        FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc] initWithNibName:@"FirstDetailView" bundle:nil];
        detailViewController = newDetailViewController;
    }

    // ...

    NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
    splitViewController.viewControllers = viewControllers;

    // ...
}

但我正在寻找的是重用详细的视图控制器,它在选择时懒惰地分配视图控制器,并在我的对象中保持对它的引用。这样,当选择另一行时,视图控制器不会被释放,并且当再次选择它时,它将被重用而不是分配新的。以下是相关代码:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    
    UIViewController <SubstitutableDetailViewController> *detailViewController = nil;

    if (row == 0) {
        if (self.firstDetailViewController == nil) {
           FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc] initWithNibName:@"FirstDetailView" bundle:nil];
           self.firstDetailViewController = newDetailViewController;
           [newDetailViewController release];
        }
        detailViewController = self.firstDetailViewController;
    }

    // ...

    NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
    splitViewController.viewControllers = viewControllers;

    // ...
}

self.firstDetailViewController在第一次选择第一行时会被实例化,然后重复使用。

当我这样做时,它在横向模式下运行良好,但在弹出菜单中点击几下后在纵向模式下它会引发异常:*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Popovers cannot be presented from a view which does not have a window.'

为什么我关心?为什么我不想重新分配视图控制器?因为在其中一些我想要执行的任务如果用户在任务尚未完成时在新的详细视图中导航,则不会被中断(被杀死)。

是否有人知道会发生什么或正在努力实现我想要实现的目标?

1 个答案:

答案 0 :(得分:0)

视图控制器旨在创建和丢弃,如果您需要在后台运行更长时间的内容,那么最好将其移动到主视图控制器或单独的对象中。

如果你想尝试重用视图控制器,可以通过在新导航控制器上设置viewControllers属性并保存在viewDidLoad中的前一个详细控制器来实现:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
        UINavigationController* navigationController = (UINavigationController*)[segue destinationViewController];

        // reuse existing controller
        navigationController.viewControllers = @[self.detailViewController];

        // update the detail controller as normal.
        [controller setDetailItem:object];
        controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
        controller.navigationItem.leftItemsSupplementBackButton = YES;
    }
}