转换为使用 iOS 8 Popover Segues 时 UISplitViewController 崩溃

Posted

技术标签:

【中文标题】转换为使用 iOS 8 Popover Segues 时 UISplitViewController 崩溃【英文标题】:UISplitViewController Crash when converting to use iOS 8 Popover Segues 【发布时间】:2014-09-30 00:55:53 【问题描述】:

我有一个 UISplitViewController,它是在 ios 6/7 天从模板设置的。我试图隐藏它以使用新的 iOS 8 UISplitViewController 工具使我的应用程序能够在 iPhone 上运行。但是,我遇到的问题都发生在使用 XCode 6 Beta 5 的 iPad 2 模拟器上。

之前我使用此代码将所选项目项传递到详细信息视图:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    self.detailViewController.detailItem = [[self fetchedResultsController] objectAtIndexPath:indexPath];

基于 iOS 8 的示例,应将其更改为 segue 以使其能够在不同大小的类和 UISplitViewControllerDisplayModes 中工作。所以我将我的单元作为源和我的详细导航控制器作为我的 segue 的目标,注释掉上面的 tableview:didSelectRowAtIndexPath 位,并实现了这个 prepareForSegue 代码:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    if ([segue.identifier isEqualToString:@"showDetail"]) 
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        self.detailViewController = (TWLDetailViewController *)[[segue destinationViewController] topViewController];
        self.detailViewController.detailItem = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    

我第一次在我的主视图中选择一行时,一切似乎都按预期工作(我看到了详细视图),但是我选择的下一个单元格导致试图解决一个已释放实例的崩溃,本质上是:*** -[DetailViewController respondsToSelector:]: message sent to deallocated instance 0x7a37a030 (我使用的是 ARC BTW,所以这里没有手工编码的保留/释放错误。)

我在 SO 上查找了一些 similar issues,并尝试在 Instruments 中使用 Zombie 分析器,如下所示(右键或控制单击图像并在新选项卡中查看它以查看完整大小):

您可以清楚地看到它正在尝试解决一个不可用的引用,因为“RefCt”变为零。我没有太多使用 Instruments 或类似调试工具的经验,但我不清楚我需要更改什么来解决这个问题,特别是因为它与 tableview:didSelectRowAtIndexPath 一起使用。

所以我的问题是:当我在明细项目之间切换时,如何更改我的主代码或明细代码以正确解除分配?对于奖励积分,很高兴知道为什么它使用以前的 tableview:didSelectRowAtIndexPath 运行良好但在 segue 上崩溃了。如果您需要查看代码的其他部分或 Instruments 跟踪,请告诉我;我很乐意分享。

【问题讨论】:

【参考方案1】:

您必须设置拆分视图控制器委托以准备继续:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    if ([segue.identifier isEqualToString:@"showDetail"]) 
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        self.detailViewController = (TWLDetailViewController *)[[segue destinationViewController] topViewController];
        self.detailViewController.detailItem = [[self fetchedResultsController] objectAtIndexPath:indexPath];
        self.splitViewController.delegate = self.detailViewController;
    

也在 didSelectRowAtIndexPath 中设置:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
    
        self.detailViewController = [[self.splitViewController.viewControllers lastObject] topViewController];
        self.splitViewController.delegate = self.detailViewController;

    

【讨论】:

谢谢霍尔格。我认为这很容易。

以上是关于转换为使用 iOS 8 Popover Segues 时 UISplitViewController 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 9 上关闭由 segue 创建的 Popover

iOS 6 Storyboard Segue 风格 Popover 与 UIPopoverController 目标崩溃

从 Modal/Popover 展开 Segue 导致开始/结束外观转换的调用不平衡

在 prepareForSegue 上为 Popover Segue 传递数据:iOS 5 中的奇怪行为

从另一个 Popover 中关闭显示为 Popover segue 的 ViewController

iOS 7 - PopOver 中的 UITableViewController 可以找到带有错误的 segue Receiver(UITableViewController) has no segu