使用Autolayout设置UIButton titleEdgeInsets和imageEdgeInsets很慢

时间:2013-03-15 11:02:23

标签: ios objective-c uibutton uikit autolayout

我有一个带有几个按钮的视图,各种尺寸。所有这些都有标题和图像。我希望将图像放在顶部,标题放在底部,居中。这可以使用以下代码正常工作:

- (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文件而不是复制每种语言的整个故事板)。所以对我而言,似乎以编程方式设置插图是要走的路,但它导致的延迟并不是真的可以接受。

有任何想法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:6)

将所有centerAlignImageAndTextForButton来自viewDidLoad的呼叫移至viewDidLayoutSubviews会将加载时间从之前的283毫秒减少到18毫秒(viewDidLoad为1毫秒,viewDidLayoutSubviews为17毫秒{1}})。

然而,我有点疑惑,为什么从viewDidLoad设置这些插图是如此昂贵......

答案 1 :(得分:0)

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

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