如何知道NSString是否适合UILabel和最后一个string的索引?

我有4行UILabel与确切的框架和字体。

我需要知道这个string是否符合标签,最后一个符合的索引是什么。

答案的核心在于Cupcake的引用发布。 无论如何,你可以使用sizeWithFont:constrainedToSize:lineBreakMode:找出一个特定的宽度的标签给定一个特定的文字包装,一个特定的字体框架的大小,例如

 CGSize size = [string sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:UILineBreakModeWordWrap]; 

sizeConstraint设置为与标签相同的宽度,但将高度设置得更大。 如果生成的size.height大于你的UILabel,那么你的string太长了。 理论上,你可以删除最后一个字符/单词,然后再试一遍,直到适合。

如果你认为这些string可能会很长,那么你可能需要换个angular度,从string的一小部分开始,不断添加字符,直到字符太大,然后就知道最后一个字符。

无论哪种方式,这个大小的迭代计算可以是相当密集的cpu操作,所以要小心。

更新:

下面是一个algorithm,它使用默认字体(但是忽略最小字体大小)返回可以放入UILabelNSString的长度:

 - (NSUInteger)fitString:(NSString *)string intoLabel:(UILabel *)label { UIFont *font = label.font; UILineBreakMode mode = label.lineBreakMode; CGFloat labelWidth = label.frame.size.width; CGFloat labelHeight = label.frame.size.height; CGSize sizeConstraint = CGSizeMake(labelWidth, CGFLOAT_MAX); if ([string sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:mode].height > labelHeight) { NSString *adjustedString; for (NSUInteger i = 1; i < [string length]; i++) { adjustedString = [string substringToIndex:i]; if ([adjustedString sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:mode].height > labelHeight) return i - 1; } } return [string length]; } 

例如,如果你检查了单词分隔模式,跳到下一个单词分隔符,然后调用sizeWithFont ,但是对于小的UILabel这可能会更有效。 如果你想利用自动换行逻辑来减less你调用sizeWithFont的次数,你可能会有这样的:

 - (NSUInteger)fitString:(NSString *)string intoLabel:(UILabel *)label { UIFont *font = label.font; UILineBreakMode mode = label.lineBreakMode; CGFloat labelWidth = label.frame.size.width; CGFloat labelHeight = label.frame.size.height; CGSize sizeConstraint = CGSizeMake(labelWidth, CGFLOAT_MAX); if ([string sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:mode].height > labelHeight) { NSUInteger index = 0; NSUInteger prev; NSCharacterSet *characterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; do { prev = index; if (mode == UILineBreakModeCharacterWrap) index++; else index = [string rangeOfCharacterFromSet:characterSet options:0 range:NSMakeRange(index + 1, [string length] - index - 1)].location; } while (index != NSNotFound && index < [string length] && [[string substringToIndex:index] sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:mode].height <= labelHeight); return prev; } return [string length]; } 

也许这里使用的字符集并不完全正确(例如,你应该包括连字符),但是如果你不需要这样做的话,它可能非常接近并且比字符一个字符更有效率。