1

有几个问题在 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];
}

我已经创建了一个UIView200x20 点的界面构建器,并将该视图分配给MCProgressBarView我正在使用的这个自定义类。当应用程序运行时,initWithCoder运行并创建一个大小为 1000x1000 点的进度视图,不管视图在 IB 上的大小。

如何强制 initWithCoder 以在 IB 上分配的正确大小运行?

注意:我不想将它硬连接到 200x20,也不想在运行时通过代码设置它。有没有办法使这项工作?

4

1 回答 1

2

TL;DR:将你的框架/边界逻辑移动到viewDidLayoutSubviews.

initWithCoder:执行帧逻辑是不安全的。你应该使用viewDidLayoutSubviews它。Apple 从 iOS 10 开始使用 1000x1000 边界。目前尚不清楚是 bug 还是故意的,但它似乎有一个净积极的结果——人们来这里询问它。;-)

事实上,initWithCoder:这种逻辑从来都不是安全的。过去,您有一个视图,其边界是 iPhone 5 的屏幕,因为那是您在 IB 中使用的,但随后该视图将增长到 iPhone 6 Plus 尺寸或 iPad 尺寸,这会导致视觉问题。

现在,Apple 只是将边界设置为 1000x1000,这对于所有情况都是不正确的。一旦在视图上执行布局传递,就会更正边界。

于 2016-10-22T18:56:55.663 回答