Edit
In my original answer, I used the label paragraph style. It turns out that for multi-line labels this actually prevents the label from being multi-line. As a result, I removed it from the calculation. Learn more about this on Github.
For those of you who are more comfortable using Open Source, definitely check out TTTAttributedLabel , where you can set the alignment of text labels to TTTAttributedLabelVerticalAlignmentTop
The trick is to subclass UILabel and override drawTextInRect . Then make sure that the text is drawn at the beginning of the label borders.
Here's a naive implementation that you can use right now:
Swift
@IBDesignable class TopAlignedLabel: UILabel { override func drawTextInRect(rect: CGRect) { if let stringText = text { let stringTextAsNSString = stringText as NSString var labelStringSize = stringTextAsNSString.boundingRectWithSize(CGSizeMake(CGRectGetWidth(self.frame), CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil).size super.drawTextInRect(CGRectMake(0, 0, CGRectGetWidth(self.frame), ceil(labelStringSize.height))) } else { super.drawTextInRect(rect) } } override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() layer.borderWidth = 1 layer.borderColor = UIColor.blackColor().CGColor } }
Swift 3
@IBDesignable class TopAlignedLabel: UILabel { override func drawText(in rect: CGRect) { if let stringText = text { let stringTextAsNSString = stringText as NSString let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width,height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil).size super.drawText(in: CGRect(x:0,y: 0,width: self.frame.width, height:ceil(labelStringSize.height))) } else { super.drawText(in: rect) } } override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() layer.borderWidth = 1 layer.borderColor = UIColor.black.cgColor } }
Objective-c
IB_DESIGNABLE @interface TopAlignedLabel : UILabel @end @implementation TopAlignedLabel - (void)drawTextInRect:(CGRect)rect { if (self.text) { CGSize labelStringSize = [self.text boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.frame), CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:self.font} context:nil].size; [super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),ceilf(labelStringSize.height))]; } else { [super drawTextInRect:rect]; } } - (void)prepareForInterfaceBuilder { [super prepareForInterfaceBuilder]; self.layer.borderWidth = 1; self.layer.borderColor = [UIColor blackColor].CGColor; } @end
Since I used IBDesignable, you can add this shortcut to the storyboard and see how it happens, this is what seems to me.
