Просмотр 1000x1000 на initWithCoder:
Есть пара вопросов, задающих это на SO, но ни один не задал это должным образом.
Я использую пользовательский индикатор выполнения, который является UIView
основанный класс с этой реализацией.
@implementation MCProgressBarView {
UIImageView * _backgroundImageView;
UIImageView * _foregroundImageView;
CGFloat minimumForegroundWidth;
CGFloat availableWidth;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
// [self bounds] is 1000x1000 here... what?
if (self) [self initialize];
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) [self initialize];
return self;
}
- (void) initialize {
UIImage * backgroundImage = [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"progress-bg" ofType:@"png"]]
resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 10.0f)];
UIImage * foregroundImage = [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"progress-bg" ofType:@"png"]]
resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 10.0f)];
_backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
_backgroundImageView.image = backgroundImage;
[self addSubview:_backgroundImageView];
_foregroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
_foregroundImageView.image = foregroundImage;
[self addSubview:_foregroundImageView];
UIEdgeInsets insets = foregroundImage.capInsets;
minimumForegroundWidth = insets.left + insets.right;
availableWidth = self.bounds.size.width - minimumForegroundWidth;
[self adjustProgress:0.0f];
}
Я создал UIView
на построителе интерфейса, чтобы быть 200x20 точек и назначил это представление для этого пользовательского класса MCProgressBarView
Я использую. Когда приложение запускается, initWithCoder
запускает и создает представление прогресса с размером 1000x1000 точек, независимо от размера представления IB.
Как заставить initWithCoder работать с правильным размером, назначенным на IB?
ПРИМЕЧАНИЕ: я не хочу жестко привязывать это к 200x20, и я не хочу устанавливать это кодом во время выполнения. Есть ли способ сделать эту работу?
1 ответ
TL;DR: переместите логику фрейма / границ в viewDidLayoutSubviews
,
initWithCoder:
не безопасно для выполнения логики кадра. Вы должны использовать viewDidLayoutSubviews
для этого. Apple использует 1000x1000 границ, начиная с iOS 10. Неясно, является ли ошибка или преднамеренной, но это, похоже, дает чистый положительный результат - люди приходят сюда и спрашивают об этом. ;-)
По факту, initWithCoder:
никогда не был безопасен для такой логики. Раньше у вас было представление, границы которого будут такими же, как на экране iPhone 5, потому что это то, что вы использовали в IB, но тогда представление увеличилось бы до размера iPhone 6 Plus или размера iPad, и это могло бы вызвать визуальные проблемы.
Теперь Apple просто устанавливает границы на 1000x1000, что неверно для всех случаев. Границы исправляются после выполнения макета в представлении.