问题 调用[super layoutSubviews]的正确方法是什么?


我刚看到他们调用的Facebook SDK for iOS [super layoutSubviews]; 最后而不是在开头 layoutSubviews 方法。

据我所知,我们应该始终把它作为第一行。 可以以不同的方式实现它会导致任何意外的UI行为吗?

- (void)layoutSubviews
{
  CGSize size = self.bounds.size;
  CGSize longTitleSize = [self sizeThatFits:size title:[self _longLogInTitle]];
  NSString *title = (longTitleSize.width <= size.width ?
                     [self _longLogInTitle] :
                     [self _shortLogInTitle]);
  if (![title isEqualToString:[self titleForState:UIControlStateNormal]]) {
    [self setTitle:title forState:UIControlStateNormal];
  }

  [super layoutSubviews];
}

3520
2017-07-10 18:25


起源

“据我所知,我们应该始终把它作为第一行”你如何“知道”那个? - matt
@matt,我相信这是iOS开发者社区使用的惯例,因为超类可能有一些默认/一般设置可能会影响我们不应用的自定义布局(如果我们在方法结束时这样做)。与在构造函数/初始化程序中调用super作为第一行类似。 - ppalancica
“超类可能有一些默认/一般设置,可能会影响我们的自定义布局不适用(如果我们在方法结束时这样做)。”是的,这绝对是真的。但这与“应该永远”不一样。 - matt


答案:


根据 UIView类参考

此方法的默认实现在iOS 5.1及更早版本中不执行任何操作。否则,默认实现使用您设置的任何约束来确定任何子视图的大小和位置。

因此,Facebook SDK示例应用程序调用 [super layoutSubviews] 在他们的实现结束时可能是最初为iOS 5.1之前的iOS版本构建的应用程序的工件。

对于iOS的更新版本,您应该致电 [super layoutSubviews] 在您的实施开始时。否则,超类将在您执行自定义布局后重新排列子视图,从而有效地忽略了您的实现 layoutSubviews()


8
2017-07-10 18:50





查看代码,在[super layoutSubviews]之前,它不是关于框架的。所以把它放在最后也可能运作良好。 我想编码器必须要检查标题并根据一些规则修改标题,他认为每次调用layoutSubviews都是一个合适的机会,所以他把代码放在这里。


4
2017-11-12 12:07





你总是要打电话 [super layoutSubviews] 最后,如果视图的内在内容大小将被更改。如果更改按钮的标题,则为内在的内容大小 UIButton 将被更改,因此是最后一次通话。

第一次打电话给 [super layoutSubviews] 始终需要,因为iOS会根据约束更新布局。 但是,实现样本的技术最正确的方法应该是:

- (void)layoutSubviews
{
 [super layoutSubviews];
  CGSize size = self.bounds.size;
  CGSize longTitleSize = [self sizeThatFits:size title:[self _longLogInTitle]];
  NSString *title = (longTitleSize.width <= size.width ?
                     [self _longLogInTitle] :
                     [self _shortLogInTitle]);
  if (![title isEqualToString:[self titleForState:UIControlStateNormal]]) {
    [self setTitle:title forState:UIControlStateNormal];
  }

  [super layoutSubviews];
}

2
2017-07-10 19:08



只是好奇:您在文档中备份的内在内容大小的声明在哪里? - ndmeiri
不幸的是,但是如果你考虑一下:内部内容大小只能用setNeedsLayout更新,它直接调用layoutSubviews。如果在layoutSubviews中更改内部内容大小(更改按钮标题),则如果之后不再调用[super layoutSubviews],则容器(Button)无法正确应用这些更改。 - seeya
@ndmeiri当我在iOS7上运行时,如果我先调用[super layoutSubviews],我就会看到运行时错误:由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因是:'执行-layoutSubviews后仍然需要自动布局。 {VIEW} -layoutSubviews的实现需要调用super。 - Matthew