弹出时,多行UILabel自动布局会折叠为1个线条

Byt*_*yte 10 uilabel ios autolayout

以下是演示该问题的示例项目

它是什么?
两个UIViewControllers在堆栈下UINavigationController.除了从一个到另一个呈现之外,每个都与彼此无关.在两个控制器中,都有一个UILabel.每个用途Autolayout.每个标签包含任意数量的行label.numberOfLines = 0.

什么有用?
从viewController A(root)转换到viewController B.B得到分配和发起.B看起来很好.

什么地方出了错?
从过渡BA.在ViewDidDisappear,标签中B决定它将不再显示超过1行,即使它numberOfLines被设置为0.当B被推入堆栈时,其标签仅显示1个衬里而不是多个.

是什么造成的?
不知道.但是在A标签numberOfLines中查找设置为0.如果要删除该行,则标签输入B不会折叠.

问题:但为什么?而且我喜欢A有多行标签,我该怎样克服这个?

代码
A.

@implementation FirstViewController
{
    BugController *_bugController;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Bar Button
    UIBarButtonItem *helpBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"BUG" style:UIBarButtonItemStylePlain target:self action:@selector(bugTapped)];
    [self.navigationItem setLeftBarButtonItem:helpBarButtonItem];

    // A sample label
    UILabel *someLabel = [[UILabel alloc] init];
    [someLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
    [someLabel setText:@"Tap BUG to see a bunch of text in many lines... tap back... then tap BUG again to see that the text has gone to 1 liner.... WTF?"];
    [self.view addSubview:someLabel];

    // Comment it out to see that problem is fixed
#warning This one liner is a culprit, removing it will make everything normal but WHY?
    [someLabel setNumberOfLines:0];
#warning end of warning


    //Constraints
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[someLabel]-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(someLabel)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[someLabel]-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(someLabel)]];
}

- (void)bugTapped
{
    // Reuse controller
    if (!_bugController) {
        _bugController = [[BugController alloc] init];
    }
    [self.navigationController pushViewController:_bugController animated:YES];
}
Run Code Online (Sandbox Code Playgroud)

@implementation BugController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Setting up stuff
    UILabel *header = [[UILabel alloc] init];
    [header setTranslatesAutoresizingMaskIntoConstraints:NO];
    [header setText:@"This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. "];
    [header setNumberOfLines:0];
    [self.view addSubview:header];

    // Constraints
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[header]-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(header)]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:header attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
}
Run Code Online (Sandbox Code Playgroud)

请在上面的示例代码链接中查看!


更新1与解决方法!在使用Misha Vyrko提供代码之后,我意识到将preferredMaxLayoutWidth设置为非零可以克服UILabel中的错误.

非破坏样本项目

添加到BugViewController

// Constraints
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[header]-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(header)]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:header attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    [header setPreferredMaxLayoutWidth:1]; // NEWLY ADDED
Run Code Online (Sandbox Code Playgroud)

我仍在寻找解释为什么会发生这种情况的解释,如果有的话,还有更好的方法.


更新2修正通过PreferredMaxLayoutWidth设置为1,label.frame.size.height实际上扩展到预期的高度,如果宽度实际上是1.这意味着,如果你有你的标签的高度的任何约束的依赖,这是行不通的.您需要将其明确设置为估计宽度.如果没有辅助设备,它将无法处理旋转,因此请注意!

小智 0

让我回答你的问题。

为什么?

我没有弄清楚,但浏览我的代码可能会回答你。我的疯狂猜测是,这是由于每次在viewDidLoad中创建一个新的 UILabel 而没有清除以前的 UILabel。

我怎样才能克服这个问题?

我尝试了一些事情。以下事情对我有用

  1. 我尝试呈现 _bugController 而不是将其推送到导航控制器中。

     [self presentViewController:_bugController animated:YES completion:nil]
    
    Run Code Online (Sandbox Code Playgroud)
  2. 不重用 bugController 对象。每次当你想要推送它时创建一个新对象。

  3. 将代码移至 viewWillAppear 并消失,使所有 UILabel 为零。这是我的代码:

第一个视图控制器

  #import "FirstViewController.h"
  #import "BugController.h"
  @interface FirstViewController ()

  @end

  @implementation FirstViewController
  {
      BugController *_bugController;
  }

  - (void)viewDidLoad
  {
      [super viewDidLoad];
    // Bar Button
    UIBarButtonItem *helpBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"BUG" style:UIBarButtonItemStylePlain target:self action:@selector(bugTapped)];
    [self.navigationItem setLeftBarButtonItem:helpBarButtonItem];
    
  }

  - (void)viewWillAppear:(BOOL)animated {
    // A sample label
    UILabel *someLabel = [[UILabel alloc] init];
    [someLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
    [someLabel setText:@"Tap BUG to see a bunch of text in many lines... tap back... then tap BUG again to see that the text has gone to 1 liner.... WTF?"];
    
    [self.view addSubview:someLabel];
    
    // Comment it out to see that problem is fixed
  #warning This one liner is a culprit, removing it will make everything normal but WHY?
    [someLabel setNumberOfLines:0];
  #warning end of warning
    
    
    //Constraints
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[someLabel]-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(someLabel)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[someLabel]-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(someLabel)]];
  }


  - (void)viewWillDisappear:(BOOL)animated {
    
    for (UIView *subView in self.view.subviews) {
      if ([subView isKindOfClass:[UILabel class]]) {
        UILabel *label = (UILabel *)subView;
        label.text = @"";
        label = nil;
      }
    }
    [super viewWillDisappear:animated];
  }

  - (void)bugTapped
  {
      // Reuse controller
      if (!_bugController) {
          _bugController = [[BugController alloc] init];
      }
      [self.navigationController pushViewController:_bugController animated:YES];
  }

  @end
Run Code Online (Sandbox Code Playgroud)

错误控制器

//

  #import "BugController.h"

  @interface BugController ()

  @end

  @implementation BugController

  - (void)viewDidLoad
  {
      [super viewDidLoad];
  }

  - (void)viewWillAppear:(BOOL)animated {
    
    UILabel *header = [[UILabel alloc] init];
    [header setTranslatesAutoresizingMaskIntoConstraints:NO];
    [header setText:@"This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. This is a multiple line thing. "];
    [header setNumberOfLines:0];
    header.tag = 111;
    [self.view addSubview:header];
    
    // Constraints
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[header]-|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(header)]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:header attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
  }

  - (void)viewWillDisappear:(BOOL)animated {
    for (UIView *subView in self.view.subviews) {
      if ([subView isKindOfClass:[UILabel class]]) {
        UILabel *label = (UILabel *)subView;
        label.text = @"";
        label = nil;
      }
    }
    [super viewWillDisappear:animated];
  }


  - (void)dismiss {
    [self dismissViewControllerAnimated:YES completion:nil];
  }


  @end
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助你!