#uilabel #autolayout #ios8 #xcode6 #layoutsubviews
#uilabel #автозапуск #ios8 #xcode6 #layoutsubviews
Вопрос:
У меня есть пользовательский UILabel, который отлично работает на iOS6 и iOS7. Но в iOS8 метод layoutSubviews этой метки (void) никогда не вызывается. Я создаю эту метку с помощью initWithFrame, поэтому этот метод должен быть вызван — и он вызывается в других версиях iOS. Что происходит с системой автозапуска в iOS8?
Комментарии:
1. Вы когда-нибудь понимали это?
2. Проблема еще хуже, так как также при использовании autolayout для subview он не получает layoutet.
3. Я создал пример проекта, показывающий проблему. Запустите на iOS 7 и 8, чтобы увидеть разницу. github.com/fabb/LabelTest
4. Я также сталкиваюсь с такой же проблемой. Вы получили какой-либо ответ на это?
5. Кажется, проблема была исправлена в бета-версии iOS 8.1.
Ответ №1:
Я просто хочу добавить этот ответ, потому что заголовок вопроса может привести к тому, что здесь будет много людей с похожими проблемами (как у меня).
С iOS 8 до 8.0.2 LayoutSubviews
вызовы ненадежны. Они могут не вызываться никогда или (в моем случае) вызываются в цикле.
Даже если вы не должны этого делать, было довольно безопасно размещать материал в layoutSubviews, но с этим ошибочным (?!) поведением это может привести к труднопрослеживаемым ошибкам.
Я не знаю, исправляет ли 8.1 все проблемы, но пройдет некоторое время, пока устройства клиентов не будут запускать 8.1, и теперь они запускают 8.0.2
Комментарии:
1. Я сталкиваюсь с той же проблемой здесь. «layoutSubviews» вызывается в цикле, чтобы охватить пользователей, использующих iOS 8.0.2, есть ли какое-либо исправление для этой ошибки?
2. нет, насколько мне известно, исправления нет. Но вы не должны пытаться поддерживать версии iOS, которые были промежуточными версиями. Если кто-то все еще использует 8.0 или 8.0.2, он может перейти на более новую версию и самостоятельно устранить проблему.
3. Да, это правда. Но, к сожалению, в приложениях мы не можем попросить каждого клиента, подключенного к этой версии, обновить свое устройство. 😉 Ну, я думаю, что я нашел обходной путь. Спасибо за ваш ответ. 🙂
Ответ №2:
У меня была такая же проблема. На самом деле layoutSubviews больше не вызывается для UILabel в iOS8, поскольку Apple не ожидает, что кто-либо использует его в качестве супервизора.
Я использую ReactiveCocoaLayout, поэтому это можно сделать, подписавшись на rcl_frameSignal или rcl_boundsSignal.
-(void)awakeFromNib
{
[ self.rcl_boundsSignal
subscribeNext:
^( NSValue* boundsValue )
{
//layout changed
} ];
}
Или вы можете использовать простой KVO, чтобы узнать, когда фрейм был изменен:
-(void)dealloc
{
[ self removeObserver: self forKeyPath: @"layer.bounds" ];
}
-(void)observeValueForKeyPath:( NSString* )keyPath
ofObject:( id )object
change:( NSDictionary* )change
context:( void* )context
{
if ( [ keyPath isEqualToString: @"layer.bounds" ] )
{
//layoutSubviews
}
else
{
[ super observeValueForKeyPath: keyPath
ofObject: object
change: change
context: context ];
}
}
-(void)awakeFromNib
{
[ self addObserver: self
forKeyPath: @"layer.bounds"
options: NSKeyValueObservingOptionNew
context: 0 ];
}
Комментарии:
1. Обратите внимание, что UIKit согласно документации НЕ совместим с KVO — даже если он работает в некоторых случаях, он может сломаться в будущем.
Ответ №3:
Ошибка была исправлена Apple в iOS 8.1 (бета-версия).
Комментарии:
1. у вас есть ссылка или что-то для резервного копирования?
2. Могу подтвердить, layoutSubview снова вызывается в бета-версии 8.1
3. Я отправил радар в Apple. И я создал пример проекта: github.com/fabb/LabelTest