Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting UIButton titleEdgeInsets and imageEdgeInsets is slow with Autolayout

I have a view with a couple of buttons, various sizes. All of them has a title and an image. I wanted to have the image on top, the title on the bottom, centered. This works fine with the following code:

- (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);
}

However, I notice a little pause before entering this view. Time Profiler in Instruments shows, that 99% of the time spent in viewDidLoad is caused by calling my method for the buttons:

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]

Various layout related things are called within [UIView(Hierarchy) layoutBelowIfNeeded], like [UIView(AdditionalLayoutSupport) recursiveLayoutEngineDidChange] or [NSLayoutConstraint addToEngine].

I know it would be possible to set these insets in Interface Builder, but not only that is a tedious work (need to 'guess' the width of the text); the app will also be localized, so the insets that are good for one language, won't be for another where text size differs (I'm using base localization for storyboards, and .strings files instead of duplicating the whole storyboard for each language). So for me it seems setting the insets programmatically is the way to go, but the lag it causes isn't really acceptable.

Any thoughts how this could resolved?

like image 414
Robert B. Avatar asked Mar 15 '13 11:03

Robert B.


1 Answers

Moving all the centerAlignImageAndTextForButton calls from viewDidLoad to viewDidLayoutSubviews reduces the loading time from the previous 283 millisecs to 18 millisecs (1 millisecs for viewDidLoad and 17 millisecs for viewDidLayoutSubviews).

However, I'm a bit puzzled, why is it so expensive to set those insets from viewDidLoad...

like image 70
Robert B. Avatar answered Oct 09 '22 16:10

Robert B.