程序化自动布局问题iOS 8.0

时间:2014-11-05 19:41:19

标签: ios objective-c iphone ios8

在iOS 8.0中看到一些有关自动布局行为的奇怪行为,并且正在寻找有关如何解决此问题的任何提示或帮助。我有一个UIView包含另一个UIView作为一个包含两个标签的子视图。这些标签的约束以编程方式添加如下:

    //StreamCaptionTextView.m
    - (void)updateConstraints
    {
      NSDictionary *views = @{
                              @"title"   : self.titleLabel,
                              @"desc"    : self.descLabel
                              };

      NSDictionary *metrics = @{
                                @"top"    : @0,
                                @"middle" : @(-2)
                                };

      [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[title]-0-|" options:0 metrics:metrics views:views]];
      [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[desc]-0-|" options:0 metrics:metrics views:views]];
      [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[title]-middle-[desc(==title)]" options:0 metrics:metrics views:views]];

      [super updateConstraints];
    }

此labelView的父视图也对labelView有适当的约束。

//StreamCaptionView which contains the StreamCaptionTextView
- (void)updateConstraints
{
  [self removeConstraints:self.constraints];

  NSMutableDictionary *views = [[NSMutableDictionary alloc] initWithDictionary:@{
                                                                                 @"image"    : self.profileImageBtn,
                                                                                 @"leftView" : self.leftText
                                                                                 }];
  NSDictionary *metrics = @{
                            @"top"        : @6,
                            @"left"       : @8,
                            @"imageSize"  : @24,
                            @"marginText" : @10,
                            @"maxWidth"   : @120
                            };

  [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[image(imageSize)]" options:0 metrics:metrics views:views]];
  [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[leftView]-top-|" options:0 metrics:metrics views:views]];

  if(self.rightAcessoryView)
  {
    views[@"rightView"] = self.rightAcessoryView ;
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-left-[image(imageSize)]-2-[leftView]-10-[rightView(maxWidth)]-10-|" options:0 metrics:metrics views:views]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[rightView]-top-|" options:0 metrics:metrics views:views]];
  }
  else
  {
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-marginText-[image(imageSize)]-2-[leftView]-marginText-|" options:0 metrics:metrics views:views]];
  }

  [super updateConstraints];
}


//This is the View that contains the captionView
- (void)setVo:(RecordingStreamItemVO *)vo
    {
      _vo = vo;

      __weak RecordingDetailVideoView *_self = self;

      self.captionView.title            = vo.user.screenname;
      self.captionView.subTitle         = vo.title;
      self.captionView.profileImageURL  = vo.user.pictureURL;

      //Here, the captionView is the rectangular blur, inside of the
      //captionView is another UIView that contains the UILabels.

    }

出于某种原因,仅在iOS 8.0上,标签未在labelView中正确呈现。这适用于iOS 8.1和7.1等。我已尝试使用[self.labelView setNeedsUpdateConstraints]使约束无效,但这似乎并不相似 解决问题。我已经搜索了相当多的内容并且我已经看到其他人在iOS 8.0中遇到autoLayout问题,但是想验证这是否是iOS问题以及我可以实现的任何可能的解决方法。

Labels Rendering Labels Not Rendering

//以下是一些照片,展示了Xcode Visual Debugger中的内容

//第一张照片在iOS 8.1上运行正常

enter image description here

//这张照片在iOS 8.0上,似乎忽略了约束。

enter image description here

// ios 8.0

layer = <CALayer: 0x17396c90>>
   |    |    |    |    |    |    |    |    |    | <StreamCaptionView: 0x15f1fe10; frame = (0 146; 320 35); layer = <CALayer: 0x15f2b3e0>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x15fcc240; frame = (10 6; 24 24); opaque = NO; layer = <CALayer: 0x15fcc340>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x1700d1c0; frame = (0 0; 24 24); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1700d240>>
   |    |    |    |    |    |    |    |    |    |    | <StreamCaptionTextView: 0x15fcc410; frame = (36 6; 274 23); layer = <CALayer: 0x15f2f620>>
   |    |    |    |    |    |    |    |    |    |    |    | <MarqueeLabel: 0x15f2f650; baseClass = UILabel; frame = (0 0; 274 13.5); text = 'test1'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x15f200b0>>
   |    |    |    |    |    |    |    |    |    |    |    |    | <UILabel: 0x17378d20; frame = (0 0; 26 0); text = 'test1'; userInteractionEnabled = NO; tag = 700; animations = { position=<CAKeyframeAnimation: 0x173b8960>; }; layer = <_UILabelLayer: 0x17378de0>>
   |    |    |    |    |    |    |    |    |    |    |    |    | <UILabel: 0x173906b0; frame = (45 0; 22 0); text = 'test1'; userInteractionEnabled = NO; tag = 701; animations = { position=<CAKeyframeAnimation: 0x173b8a60>; }; layer = <_UILabelLayer: 0x17390770>>
   |    |    |    |    |    |    |    |    |    |    |    | <MarqueeLabel: 0x17390c40; baseClass = UILabel; frame = (0 11.5; 274 13.5); text = 'Test'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x17390d60>>
   |    |    |    |    |    |    |    |    |    |    |    |    | <UILabel: 0x17390940; frame = (0 0; 17 0); text = 'Test'; userInteractionEnabled = NO; tag = 700; animations = { position=<CAKeyframeAnimation: 0x173b93a0>; }; layer = <_UILabelLayer: 0x17390a00>>
   |    |    |    |    |    |    |    |    |    |    |    |    | <UILabel: 0x173a1640; frame = (82 0; 48 0); text = 'Test'; userInteractionEnabled = NO; tag = 701; animations = { position=<CAKeyframeAnimation: 0x173b94a0>; }; layer = <_UILabelLayer: 0x173a1700>>
   |    |    |    |    |    |    |    |    | <_UITableViewCellSeparatorView: 0x173ae010; frame = (15 179.5; 305 0.5); layer = <CALayer: 0x173ad1d0>>
   |    |    |    |    |    |    |    | <TimePublishedDetailView: 0x173a1d60; frame = (238.5 20; 71.5 11); layer = <CALayer: 0x173a1ef0>>
   |    |    |    |    |    |    |    |    | <UIImageView: 0x173a21e0; frame = (0 0; 9 9); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x173a2260>>
   |    |    |    |    |    |    |    |    | <UILabel: 0x173a85d0; frame = (16 -2; 55.5 13.5); text = '5 hours ago'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x173a8550>>

更新

我实际上在父视图控制器中通过一个非常简单的修复解决了这个问题。

- (void)viewDidLoad
{
  [super viewDidLoad];
  // Do any additional setup after loading the view.

  [self.view addSubview:self.detailsView];
  [self.view setNeedsUpdateConstraints];
}

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  [self loadDetails];

  [self.view layoutIfNeeded]; //This fixed the iOS 8.0 problem

}

//In my case the self.detailsView property contains the view hierarchy which 
//contains the UILabels that weren't being rendered properly way down
//in the view hierarchy. calling layoutIfNeeded fixes this problem for me. 

1 个答案:

答案 0 :(得分:0)

首先,您需要确切知道发生了什么。在方便的位置暂停应用程序并在控制台中输入以下命令:

po [[UIWindow keyWindow] recursiveDescription]

如果这对您没有帮助,请立即将其作为参考发布在此处。

通常,手动布局会导致布局不足或过度约束,而Interface Builder会为此发出警告。对于我没有更广泛的调试信息,我仍然有点失明。

现在我有了这些日志,我注意到以下几行:

   |    |    |    |    |    |    |    |    |    |    |    |    | <UILabel: 0x17378d20; frame = (0 0; 26 0); text = 'test1'; userInteractionEnabled = NO; tag = 700; animations = { position=<CAKeyframeAnimation: 0x173b8960>; }; layer = <_UILabelLayer: 0x17378de0>>
   |    |    |    |    |    |    |    |    |    |    |    |    | <UILabel: 0x173906b0; frame = (45 0; 22 0); text = 'test1'; userInteractionEnabled = NO; tag = 701; animations = { position=<CAKeyframeAnimation: 0x173b8a60>; }; layer = <_UILabelLayer: 0x17390770>>

因此所有标签似乎都没有高度。

此行可能已关闭:

@"V:|-top-[title]-middle-[desc(==title)]"

它似乎没有点击到底部所以它不能给出标题高度和desc?尝试做这样的事情:

@"V:|-top-[title]-middle-[desc(==title)]-|"

或给出最低身高:

@"V:|-top-[title(>=10)]-middle-[desc(==title)]"