【问题标题】:What is the correct way to call [super layoutSubviews]?调用 [super layoutSubviews] 的正确方法是什么?
【发布时间】:2015-09-29 14:47:25
【问题描述】:

我刚刚在 iOS 版 Facebook SDK 中看到他们在末尾调用 [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];
}

【问题讨论】:

  • “据我所知,我们应该始终将其作为第一行”您是如何“知道”这一点的?
  • @matt,我相信这是 iOS 开发者社区使用的约定,因为超类可能有一些默认/常规设置,可能会影响我们不应用的自定义布局(如果我们在方法结束)。类似于在构造函数/初始化器中调用 super 作为第一行。
  • “超类可能有一些默认/常规设置,可能会影响我们的自定义布局不被应用(如果我们在方法结束时这样做)。”是的,这绝对是真的。但这与“应该总是”不同。

标签: ios objective-c facebook sdk


【解决方案1】:

根据UIView Class Reference

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

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

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

【讨论】:

    【解决方案2】:

    查看代码,在[super layoutSubviews]之前,它与框架无关。所以把它放在最后也可以很好地工作。 我猜编码员一定是想检查标题并根据一些规则修改标题,他认为每次调用layoutSubviews都是一个合适的机会,所以他把代码放在这里。

    【讨论】:

      【解决方案3】:

      如果视图的内在内容大小将被更改,您总是必须最后调用[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];
      }
      

      【讨论】:

      • 只是好奇:您关于内在内容大小的声明是否在任何地方的文档中得到支持?
      • 很遗憾没有,但是如果你想一想:固有的内容大小只能用setNeedsLayout来更新,它直接调用layoutSubviews。如果您在 layoutSubviews 中更改内部内容大小(更改按钮标题),如果之后不会调用 [super layoutSubviews],则容器(按钮)无法正确应用这些更改。
      • @ndmeiri 在 iOS7 上运行时,如果我先调用 [super layoutSubviews],我会看到运行时错误:由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“执行后仍需要自动布局-layoutSubviews。 {VIEW} 的 -layoutSubviews 实现需要调用 super。'
      猜你喜欢
      • 2021-10-22
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多