【问题标题】:Setting UIButton titleEdgeInsets and imageEdgeInsets is slow with Autolayout使用 Autolayout 设置 UIButton titleEdgeInsets 和 imageEdgeInsets 很慢
【发布时间】:2013-03-04 01:36:18
【问题描述】:

我有一个带有几个按钮的视图,大小不一。它们都有一个标题和一个图像。我想让图像在顶部,标题在底部,居中。这适用于以下代码:

- (void)centerAlignImageAndTextForButton:(UIButton*)button
{
    CGFloat spacing = 5;
    CGSize imageSize = button.imageView.frame.size;
    button.titleEdgeInsets = UIEdgeInsetsMake(0, -imageSize.width, -(imageSize.height + spacing), 0);
    CGSize titleSize = button.titleLabel.frame.size;
    button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + spacing), 0, 0, -titleSize.width);
}

但是,我注意到在进入此视图之前有一点停顿。 Instruments 中的 Time Profiler 显示,在 viewDidLoad 中花费的 99% 时间是由调用我的按钮方法引起的:

283.0ms  -[XViewController viewDidLoad]
282.0ms    -[XViewController centerAlignImageAndTextForButton:]
141.0ms      -[UIButton imageView]
 98.0ms        -[UIView(Hierarchy) layoutBelowIfNeeded]
141.0ms      -[UIButton titleLabel]
103.0ms        -[UIView(Hierarchy) layoutBelowIfNeeded]

[UIView(Hierarchy) layoutBelowIfNeeded] 中调用各种布局相关的东西,如[UIView(AdditionalLayoutSupport) recursiveLayoutEngineDidChange][NSLayoutConstraint addToEngine]

我知道可以在 Interface Builder 中设置这些插图,但这不仅是一项繁琐的工作(需要“猜测”文本的宽度);该应用程序也将被本地化,因此适用于一种语言的插图不会适用于文本大小不同的另一种语言(我对故事板和 .strings 文件使用基本本地化,而不是为每种语言复制整个故事板)。所以对我来说,似乎以编程方式设置插图是可行的方法,但它导致的滞后是不能接受的。

有什么想法可以解决这个问题吗?

【问题讨论】:

  • 你为什么不在layoutSubViews上设置它们?

标签: ios objective-c uibutton uikit autolayout


【解决方案1】:

将所有 centerAlignImageAndTextForButton 调用从 viewDidLoad 移动到 viewDidLayoutSubviews 将加载时间从之前的 283 毫秒减少到 18 毫秒(viewDidLoad 为 1 毫秒,viewDidLayoutSubviews 为 17 毫秒)。

不过,我有点疑惑,为什么从viewDidLoad设置这些插图这么贵...

【讨论】:

  • 可能是因为在 viewDidLoad 时,您的布局都没有执行,所以还需要做更多的工作?在 viewDidLayout... 您的大部分布局已经完成,因此调整插图是一种调整,而不是完整的布局。这是一个猜测。顺便说一句,如果您对按钮中的边缘插图感兴趣,我最近在这里写过它们(带有示例项目):commandshift.co.uk/blog/2013/03/12/uibutton-edge-insets
  • 是的,在寻找解决方案时偶然发现了该帖子。你的猜测是有道理的,当我在文档中找到viewDidLayoutSubviews 方法时,我想到了一些类似的想法,这就是我(幸运地)尝试它的原因。
【解决方案2】:

在自定义UIButton 子类中从awakeFromNib 缓慢调用titleLabel 时遇到类似问题。由于按钮的大量和/或非平凡的生命周期,将代码移动到视图控制器是不可取的。将代码移至layoutSubviews 并没有帮助。最终我将代码移至didMoveToSuperview 并解决了问题。

- (void)didMoveToSuperview
{
    [super didMoveToSuperview];
    self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
    self.titleLabel.numberOfLines = 2;
    self.titleLabel.textAlignment = NSTextAlignmentCenter;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 2017-04-01
    相关资源
    最近更新 更多