Here is the sample project demonstrating the problem
这是什么?
UIViewControllers
下的堆栈中有两个UINavigationController
。除了从一个到另一个呈现之外,每个都与彼此无关。在两个控制器中,都有一个UILabel
。每个都使用Autolayout
。每个标签都包含任意数量的行label.numberOfLines = 0
。
什么有效?
从viewController A
(root)转换到viewController B
。 B
被分配并启动。 B
看起来很好。
出了什么问题?
从B
过渡到A
。在ViewDidDisappear
,B
中的标签决定它将不再显示超过1行,即使其numberOfLines
设置为0.当B
被推入堆栈时,标签只显示1个衬垫而不是多个。
是什么造成的?
不知道。但是查看A
标签numberOfLines
设置为0.如果要删除该行,则B
中的标签不会折叠。
问题:但是为什么?我喜欢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];
}
B
@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]];
}
请在上面的示例代码链接中查看!
使用变通方法更新1!使用code provided by 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
我仍然在寻找解释为什么会发生这种情况的解释,以及更好的解决方法。
更新2更正通过将PreferredMaxLayoutWidth设置为1,label.frame.size.height
实际上会扩展到预期的高度,如果宽度实际为1.这意味着如果您有任何约束依赖标签的高度,无效。您需要将其明确设置为估计宽度。如果没有帮助,将无法处理轮换,请注意这一点!
答案 0 :(得分:4)
在bugController中,如果你设置了所有约束,你就没有足够的布局标签约束
@interface BugController ()
@property (nonatomic, strong) UILabel *header;
@end
@implementation BugController
- (void)viewDidLoad
{
[super viewDidLoad];
// Setting up stuff
self.header = [[UILabel alloc] init];
[self.header setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.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! "];
[self.header setBackgroundColor:[UIColor redColor]];
[self.header setNumberOfLines:0];
[self.view addSubview:self.header ];
// Constraints
// [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[header]-|"
// options:0
// metrics:0
// views:NSDictionaryOfVariableBindings(header)]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.header
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.header
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.header
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.view
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0]];
self.header.preferredMaxLayoutWidth = self.view.frame.size.width;
[self.view needsUpdateConstraints];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
self.header.preferredMaxLayoutWidth = self.view.frame.size.width;
[self.view needsUpdateConstraints];
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
@end
答案 1 :(得分:1)
Here is the link for the working project.
问题的根源尚不清楚,但遵循“如果你不知道该做什么,做点什么”的原则,我通过将两个标签存储为属性来实现它(这可能是不必要的,可能是实例变量没关系)并在两个视图控制器中实现以下回调(记住,你说,删除一行[someLabel setNumberOfLines:0];在第一个控制器中修复第二个,所以这里我们去):
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.yourLabel.numberOfLines = 1;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.yourLabel.numberOfLines = 0;
}
它闻起来像UILabel类中的一个错误,但我确定并不是那么酷。祝你好运!
答案 2 :(得分:0)
让我回答你的问题。
我没弄清楚但是通过我的代码可能会回答你。我的猜测是,它每次都会在 viewDidLoad 中创建一个新的UILabel,而不会清除之前的那些。
我试图提供_bugController而不是在导航控制器中推送它。
[self presentViewController:_bugController animated:YES completion:nil]
不重用bugController对象。每次想要推送它时都会创建一个新对象。
将您的代码移至viewWillAppear并在消失时使所有UILabel为零。这是我的代码:
FirstViewController
#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
BugController
//
#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
我希望这可以帮到你!
答案 3 :(得分:0)
您遇到的行为非常奇怪。这是一种解决方法:
我建议您停止重复使用BugController。这是一个干净的解决方案,您不必显式缓存ViewControllers。 (操作系统可以自行处理效率,如果您遵守MVC标准,您应该可以根据基础模型数据随时重建视图控制器)
要执行此操作,请删除BugController iVar,并将bugTapped
更改为:
- (void)bugTapped
{
BugController *bugVC = [[BugController alloc] init];
[self.navigationController pushViewController:bugVC animated:YES];
}