Установка UIButton titleEdgeInsets и imageEdgeInsets медленно с 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);
}
Тем не менее, я замечаю небольшую паузу перед входом в это представление. Time Profiler in Instruments показывает, что 99% времени, проведенного в viewDidLoad, вызвано вызовом моего метода для кнопок:
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 вместо дублирования всей раскадровки для каждого языка). Так что для меня это, по-видимому, программирование программ, это путь, но отставание, которое оно вызывает, не очень приемлемо.
Любые мысли о том, как это можно решить?
Ответы
Ответ 1
Перемещение всех вызовов centerAlignImageAndTextForButton
с viewDidLoad
на viewDidLayoutSubviews
уменьшает время загрузки с предыдущих 283 миллисекунд до 18 миллисекунд (1 миллисекунды для viewDidLoad
и 17 миллисекунгов для viewDidLayoutSubviews
).
Однако, я немного озадачен, почему так дорого устанавливать эти вставки из viewDidLoad
...
Ответ 2
Имела аналогичную проблему при медленном вызове titleLabel
от awakeFromNib
в пользовательском подклассе UIButton
. Перемещение кода для просмотра контроллера было нежелательным из-за большого количества и/или нетривиального жизненного цикла кнопок. Перемещение кода на layoutSubviews
не помогло. В конце концов я переместил код в didMoveToSuperview
, и он решил проблему.
- (void)didMoveToSuperview
{
[super didMoveToSuperview];
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.titleLabel.numberOfLines = 2;
self.titleLabel.textAlignment = NSTextAlignmentCenter;
}