Это не правильно:
lblTemp.lineBreakMode = NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail
lblTemp.numberOfLines = 0;
NSLineBreakMode определен в NSParagraphStyle.h как:
typedef NS_ENUM(NSInteger, NSLineBreakMode) { /* What to do with long lines */
NSLineBreakByWordWrapping = 0, /* Wrap at word boundaries, default */
NSLineBreakByCharWrapping, /* Wrap at character boundaries */
NSLineBreakByClipping, /* Simply clip */
NSLineBreakByTruncatingHead, /* Truncate at head of line: "...wxyz" */
NSLineBreakByTruncatingTail, /* Truncate at tail of line: "abcd..." */
NSLineBreakByTruncatingMiddle /* Truncate middle of line: "ab...yz" */
} NS_ENUM_AVAILABLE_IOS(6_0);
Обратите внимание, что это NS_ENUM, а не NS_OPTION, поэтому он не предназначен для использования в качестве маски. Для получения дополнительной информации см это .
В действительности использование оператора | для этих констант приводит к маске, совпадающей с NSLineBreakByTruncatingTail:
(NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail) == 4
NSLineBreakByTruncatingTail == 4
Насколько я знаю, усечение последней строки в Базовом тексте и также перенос слов не может быть сделано с помощью простых API-интерфейсов CTFramesetterCreateWithAttributedString & CTFrameDraw , но может быть выполнено с построчной разметкой, которая UILabel должен делать.
iOS 6 упрощает это, предоставляя новые API рисования в NSStringDrawing.h:
typedef NS_ENUM(NSInteger, NSStringDrawingOptions) {
NSStringDrawingTruncatesLastVisibleLine = 1 << 5, // Truncates and adds the ellipsis character to the last visible line if the text doesn't fit into the bounds specified. Ignored if NSStringDrawingUsesLineFragmentOrigin is not also set.
NSStringDrawingUsesLineFragmentOrigin = 1 << 0, // The specified origin is the line fragment origin, not the base line origin
NSStringDrawingUsesFontLeading = 1 << 1, // Uses the font leading for calculating line heights
NSStringDrawingUsesDeviceMetrics = 1 << 3, // Uses image glyph bounds instead of typographic bounds
} NS_ENUM_AVAILABLE_IOS(6_0);
@interface NSAttributedString (NSExtendedStringDrawing)
- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
@end
Так что, если вы используете UILabel, вы хотите, чтобы NSParagraphStyle вашего NSAttributedString или lineBreakMode на самой метке были установлены на:
NSLineBreakByTruncatingTail
И свойство numberOfLines на метке должно быть установлено в 0.
Из заголовков UILabel на numberOfLines:
// if the height of the text reaches the # of lines or the height of the view is less than the # of lines allowed, the text will be
// truncated using the line break mode.
Из документации UILabel:
This property controls the maximum number of lines to use in order to fit the label’s text into its bounding rectangle. The default value for this property is 1. To remove any maximum limit, and use as many lines as needed, set the value of this property to 0.
If you constrain your text using this property, any text that does not fit within the maximum number of lines and inside the bounding rectangle of the label is truncated using the appropriate line break mode.
Единственная проблема, которая возникает с этой несколько непонятной функцией UILabel, заключается в том, что вы не можете получить размер перед рисованием (что необходимо для некоторых динамических макетов UITableView + UITableViewCell), не прибегая к изменению NSParagraphStyle NSAttributedString на лету.
Начиная с iOS 6.1.4, вызов -boundingRectWithSize: options: context с NSAttributedString с режимом разрыва строки NSLineBreakByTruncatingTail (для UILabel), возвращает неверную высоту одной строки , даже если следующие параметры передано:
(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine)
(Обратите внимание, что NSStringDrawingUsesLineFragmentOrigin является необходимостью для многострочных строк.)
Что еще хуже, так это то, что lineBreakMode UILabel не переопределяет стиль абзаца NSAttributedStrings, поэтому вам нужно изменить стиль абзаца приписанной строки для расчета размера, а затем передать его UILabel, чтобы он мог нарисуй его.
То есть NSLineBreakByWordWrapping для -boundingRectWithSize: options: context и NSLineBreakByTruncatingTail для UILabel (поэтому он может использовать NSStringDrawingTruncatesLastVisibleLine для внутреннего использования или для любых других действий, чтобы обрезать последнюю строку)
Единственная альтернатива, если вы не хотите изменять стиль абзаца вашей строки более одного раза, - это сделать простой подкласс UIView, который переопределяет -drawRect: (с соответствующим параметром contentMode, также настроенным на перерисовку), и использует iOS 6 новый API рисования:
- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
Не забывайте использовать NSLineBreakByWordWrapping и передавать (NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine) в качестве параметров.
Наконец, перед iOS 6, если вы хотите сделать перенос слов + усечение хвоста для приписанной строки, вам придется делать построчное размещение самостоятельно с Core Text.