Why can't I change the frame of my UILabel?

2019-03-25 20:11发布

问题:

I have been trying for two days to modify the frame of a UILabel, which is ridiculous... The UILabel is an IBOutlet, but that is not the reason why it's not working: I tried to create a UILabel programatically and it still didn't work. Here is how I do it:

self.descriptionLabel.text = description;
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;

CGSize textSize = [self.descriptionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0]
                                         constrainedToSize:CGSizeMake(self.descriptionLabel.frame.size.width, FLT_MAX)
                                             lineBreakMode:self.descriptionLabel.lineBreakMode];
CGFloat frameHeight = textSize.height;
CGRect frame = self.descriptionLabel.frame;
frame.size.height = frameHeight;
self.descriptionLabel.frame = frame;

CGRect bounds = self.descriptionLabel.frame;
bounds.origin.x = self.descriptionLabel.frame.origin.x + 10.0;
bounds.size.width = self.descriptionLabel.frame.size.width - 20.0;
self.descriptionLabel.bounds = bounds;
self.descriptionLabel.numberOfLines = 0;

I already asked on IRC and they told me that there is no reason why the frame would not be changed...

I also tried to create a frame with CGRectMake and give it arbitrary value but that didn't do the trick either..

Does anyone know what might be the problem please?

Edit 1: I logged the frame before and after, and I got odd results:

Before: 0.000000 0.000000 0.000000 0.000000
After: 0.000000 0.000000 0.000000 33525.000000

The height after I set the frame is the only value that makes sense (I have a lot of text in the label on purpose).

Edit 2: I changed the code as follows, the log says that the frame changed but on the simulator it didn't change; I proved it by adding red borders to the layer of the UILabel.

self.descriptionLabel.text = description;
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;

CGSize textSize = [self.descriptionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0]
                                         constrainedToSize:CGSizeMake(self.view.frame.size.width, FLT_MAX)
                                             lineBreakMode:self.descriptionLabel.lineBreakMode];
CGFloat frameHeight = textSize.height;
CGRect frame = CGRectMake(0.0, 300.0, self.view.frame.size.width, frameHeight);
self.descriptionLabel.frame = frame;

DDLogInfo(@"After: %f %f %f %f", self.descriptionLabel.frame.origin.x, self.descriptionLabel.frame.origin.y, self.descriptionLabel.frame.size.width, self.descriptionLabel.frame.size.height);
// After: 0.000000 300.000000 320.000000 585.000000

self.descriptionLabel.numberOfLines = 0;
self.descriptionLabel.layer.borderColor = [UIColor redColor].CGColor;
self.descriptionLabel.layer.borderWidth = 2;

回答1:

If you're using auto layout, you shouldn't be doing any setting of frames -- either turn off auto layout, or use constraints to change the size of your label. The easiest way to do this is to give your label a height constraint (and width too, if you want a constant width) in IB, and make an IBOutlet to it. Then, in code, change the constant value of that constraint based on the value you get from sizeWithFont:constrainedToSize:lineBreakMode:.



回答2:

Your label has a zero frame to begin with, so, when you do this:

CGSize textSize = [self.descriptionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0]
                                         constrainedToSize:CGSizeMake(self.descriptionLabel.frame.size.width, FLT_MAX)
                                             lineBreakMode:self.descriptionLabel.lineBreakMode];

You're asking the sizeWithFont method to do something effectively impossible - tell you the height that is required when no width is allowed. The response it provides (33525.000000) is probably the height if one character is allowed on each line or something like that.

So, either set the width of the label before you start, or provide the allowed width to the sizeWithFont method and then set the label size using the response (not just the height).

Also, consider what you're trying to do by changing the bounds. Comment that code out till you get the frame right at least, then you can add it back in and check it actually does what you want.