viewDidLayoutSubviews陷入了无限循环的空白方法

时间:2017-12-20 18:36:06

标签: ios uitableview infinite-loop viewdidlayoutsubviews

我有一个在UIStoryboard中使用UITableView设置的视图控制器。 UITableView在四个方面都受限于控制器的SafeArea。

以前可能会问过这个问题,但每次我发现问题时,都是因为viewDidLayoutSubviews中发生了导致循环发生的变化。我有一个viewDidLayoutSubviews的空白实现和基本的UITableViewCells(没有nib)。然而在iOS 11,Xcode 9.2中,轻击tableview会导致viewDidLayoutSubviews在无限循环中被调用。这是我的实施:

- (void)viewDidLayoutSubviews {

    NSLog(@"viewDidLayoutSubviews");
    [super viewDidLayoutSubviews];
}

我无法弄清楚我的生活是如何发生的。

编辑:控制器有一个NavigationController,是UISplitViewController的主控制器,它嵌入在BannerViewController中(来自iAdSuite示例)。

编辑:这发生在模拟器上所有设备上的iOS 11(最高11.2)上。不会发生iOS 10.3。在iOS 10.3中甚至没有调用viewDidLayoutSubviews。当我只使用带有UIViewController / TableView的Nav Controller代替UISplitViewController / BannerViewController时,我得到了相同的结果。所以似乎问题并没有在那里引入,而是来自iOS 11中发生的事情。

编辑:所以这很奇怪 - 似乎只有在为导航控制器选择了大型游戏时才会发生这种情况!

if (@available(iOS 11.0, *)) {
    self.navigationController.navigationBar.prefersLargeTitles = YES;
    self.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeAlways;
}

编辑:这个问题很容易复制。我下载了Apple的iAd Suite示例代码,并使用了SplitNavigationController项目。我更新了iOS 11的项目,包括更新故事板以使用安全区域布局指南。我将MasterViewController从UITableViewController更改为带有UITableView的UIViewController,我将其约束到故事板中的Safe Area布局指南。我将prefersLargeTitles和largeTitleDisplayMode添加到MasterViewController中。我在viewDidLayoutSubviews方法中添加了一个NSLog语句,因此可以很容易地观察到这种行为。我认为这是iOS 11的一个真正的问题,我会尽力找到它的底部,如果其他人可以提供任何想法或建议,我也将不胜感激。

编辑:matt能够重现此问题并将其发布到GitHub项目中,可在以下链接中找到(感谢matt!):InfiniteLayoutSubviewsBug

1 个答案:

答案 0 :(得分:2)

编辑这绝对是iOS 11至少iOS 11.2中的一个错误,但在iOS 12中该错误已不复存在。

您好像发现了一个错误。我能够在一个最小的示例项目中重现该问题,我在GitHub上发布了这个项目:

https://github.com/mattneub/InfiniteLayoutSubviewsBug

下载项目并运行它。您将看到一个包含三行的简单表格。滚动表格视图向上然后放手。观看控制台。我们每隔1/60秒就会反复拨打viewDidLayoutSubviews来电话。

请注意,这是由我们的代码中的递归布局循环引起的 not 。我的例子甚至没有打电话给super。它所做的就是记录。这是运行时本身永远重复调用viewDidLayoutSubviews。在发生这种情况时,我们的代码(print除外)都没有运行。

其他观察:

  • 正如您所正确观察的那样,如果您更改示例以使导航栏不使用大型标题,则问题就会消失。

  • 如果更改示例以使表格视图未使用自动布局定位,则问题就会消失。

  • 如果您更改示例(更精确地说),以便视图控制器是UITableViewController子类,问题就会消失;我们会多次调用viewDidLayoutSubviews而不是永远,只是在滚动时。