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

Posted

技术标签:

【中文标题】在 UISplitViewController 中重用详细视图控制器【英文标题】:Reusing detailed view controller in UISplitViewController 【发布时间】:2011-05-11 10:50:45 【问题描述】:

基本上,当我实现像 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;

    // ...

但我正在寻找的是重用详细的视图控制器,即在选择视图控制器时懒惰地分配它,并在我的对象中保留对它的引用。 That way when another row is selected the view controller is not deallocated and when it is selected again it would be reused instead of allocating a new one.以下是相关代码:

- (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.'

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

有没有人知道会发生什么或者我正在努力实现的目标的有效实施?

【问题讨论】:

如果表开始加载的行不是 0 怎么办?在这种情况下,detailViewController 将为 nil。 查看类似post的答案 【参考方案1】:

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

如果您确实想尝试重用视图控制器,这可以通过在新导航控制器上设置 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;
    

【讨论】:

以上是关于在 UISplitViewController 中重用详细视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

UISplitViewController:在 detailView 中导航

在 UISplitViewController 中使用 SwiftUI 列表侧边栏

UISplitViewController:为啥我不应该在导航或标签栏界面中显示它?

UISplitViewController 一致分隔符

在 UISplitViewController 中隐藏 MasterView

嵌套详细视图(UISplitViewController)中缺少后退按钮