如何从UILabel的第n行获取文本?
有没有一种简单的方法来获取(或者简单地显示)来自UILabel中给定行的文本?
我的UILabel正确显示我的文本,并把它铺设漂亮,但偶尔我需要能够显示某些行,但显然我需要知道UILabel如何定位一切这样做。
我知道这可以很容易地完成一个子string,但我需要知道该行的开始和结束点。
或者我可以滚动UILabel,如果有某种types的UILabel帧的偏移量,并隐藏我不想看到的内容的其余部分。
我还没有发现任何可以轻易完成的事情。 任何人有什么好主意?
谢谢
iphaaw
我不认为有这样做的本地方式(如“takethenline”方法)。
我可以找出一个棘手的解决scheme,但我不知道是最好的。
你可以把你的标签分成几个字。
然后你可以循环数组,并检查文本的高度,直到这样的话:
NSString *texttocheck; float old_height = 0; int linenumber = 0; for (x=0; x<[wordarray lenght]; x++) { texttocheck = [NSString stringWithFormat:@"%@ %@", texttocheck, [wordarray objectAtIndex:x]]; float height = [text sizeWithFont:textLabel.font constrainedToSize:CGSizeMake(textLabel.bounds.size.width,99999) lineBreakMode:UILineBreakModeWordWrap].height; if (old_height < height) { linenumber++; } }
如果高度发生变化,则表示在单词前面有一个换行符。
我不能检查语法是否现在正确写入,所以你必须自己检查。
我有更好的方法来find它。
你可以在CoreText.framework的帮助下得到这个。
1.添加CoreText.framework 。
2.导入#import <CoreText/CoreText.h>
导入#import <CoreText/CoreText.h>
。
然后使用下面的方法:
- (NSArray *)getLinesArrayOfStringInLabel:(UILabel *)label { NSString *text = [label text]; UIFont *font = [label font]; CGRect rect = [label frame]; CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL); NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text]; [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)]; CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr); CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000)); CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL); NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame); NSMutableArray *linesArray = [[NSMutableArray alloc]init]; for (id line in lines) { CTLineRef lineRef = (__bridge CTLineRef )line; CFRange lineRange = CTLineGetStringRange(lineRef); NSRange range = NSMakeRange(lineRange.location, lineRange.length); NSString *lineString = [text substringWithRange:range]; [linesArray addObject:lineString]; } return (NSArray *)linesArray; }
调用这个方法:
NSArray *linesArray = [self getLinesArrayOfStringInLabel:yourLabel];
现在你可以使用linesArray
。
Swift 2(Xcode 7)版本(testing,并从Swift 1的答案重新编辑)
func getLinesArrayOfStringInLabel(label:UILabel) -> [String] { let text:NSString = label.text! // TODO: Make safe? let font:UIFont = label.font let rect:CGRect = label.frame let myFont:CTFontRef = CTFontCreateWithName(font.fontName, font.pointSize, nil) let attStr:NSMutableAttributedString = NSMutableAttributedString(string: text as String) attStr.addAttribute(String(kCTFontAttributeName), value:myFont, range: NSMakeRange(0, attStr.length)) let frameSetter:CTFramesetterRef = CTFramesetterCreateWithAttributedString(attStr as CFAttributedStringRef) let path:CGMutablePathRef = CGPathCreateMutable() CGPathAddRect(path, nil, CGRectMake(0, 0, rect.size.width, 100000)) let frame:CTFrameRef = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil) let lines = CTFrameGetLines(frame) as NSArray var linesArray = [String]() for line in lines { let lineRange = CTLineGetStringRange(line as! CTLine) let range:NSRange = NSMakeRange(lineRange.location, lineRange.length) let lineString = text.substringWithRange(range) linesArray.append(lineString as String) } return linesArray }
回答正确的版本!
-(NSArray *)getLinesArrayOfStringInLabel:(UILabel *)label { NSString *text = [label text]; UIFont *font = [label font]; CGRect rect = [label frame]; CTFontRef myFont = CTFontCreateWithName(( CFStringRef)([font fontName]), [font pointSize], NULL); NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text]; [attStr addAttribute:(NSString *)kCTFontAttributeName value:( id)myFont range:NSMakeRange(0, attStr.length)]; CFRelease(myFont); CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString(( CFAttributedStringRef)attStr); CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000)); CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL); NSArray *lines = ( NSArray *)CTFrameGetLines(frame); NSMutableArray *linesArray = [[NSMutableArray alloc]init]; for (id line in lines) { CTLineRef lineRef = ( CTLineRef )line; CFRange lineRange = CTLineGetStringRange(lineRef); NSRange range = NSMakeRange(lineRange.location, lineRange.length); NSString *lineString = [text substringWithRange:range]; CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attStr, lineRange, kCTKernAttributeName, (CFTypeRef)([NSNumber numberWithFloat:0.0])); CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attStr, lineRange, kCTKernAttributeName, (CFTypeRef)([NSNumber numberWithInt:0.0])); //NSLog(@"''''''''''''''''''%@",lineString); [linesArray addObject:lineString]; } [attStr release]; CGPathRelease(path); CFRelease( frame ); CFRelease(frameSetter); return (NSArray *)linesArray; }
Swift 3 – Xcode 8.1
我已经把以前的答案的代码放在一起,创build一个Swift 3,与UILabel
兼容的Xcode 8.1 extension
,返回标签的第一行。
import CoreText extension UILabel { /// Returns the String displayed in the first line of the UILabel or "" if text or font is missing var firstLineString: String { guard let text = self.text else { return "" } guard let font = self.font else { return "" } let rect = self.frame let attStr = NSMutableAttributedString(string: text) attStr.addAttribute(String(kCTFontAttributeName), value: CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil), range: NSMakeRange(0, attStr.length)) let frameSetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString) let path = CGMutablePath() path.addRect(CGRect(x: 0, y: 0, width: rect.size.width + 7, height: 100)) let frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil) guard let line = (CTFrameGetLines(frame) as! [CTLine]).first else { return "" } let lineString = text[text.startIndex...text.index(text.startIndex, offsetBy: CTLineGetStringRange(line).length-2)] return lineString } }
要使用它,简单的调用你的UILabel
实例的firstLineString
就像这样:
let firstLine = myLabel.firstLineString
这是用于获取标签中所有行的Swift 3版本。 (@fredpi有一个类似的答案,但它只是第一行)
extension UILabel { func getArrayOfLinesInLabel() -> [String] { let text = NSString(string: self.text ?? "-- -- -- --") let font = self.font ?? // Your default font here let rect = self.frame let myFont = CTFontCreateWithName(font.fontName as CFString?, font.pointSize, nil) let attStr = NSMutableAttributedString(string: text as String) attStr.addAttribute(String(kCTFontAttributeName), value:myFont, range: NSRange(location: 0, length: attStr.length)) let frameSetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString) let path = CGPath(rect: CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height), transform: nil) let frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil) guard let lines = CTFrameGetLines(frame) as? [CTLine] else { return [] } var linesArray = [String]() for line in lines { let lineRange = CTLineGetStringRange(line) let range = NSRange(location: lineRange.location, length: lineRange.length) let lineString = text.substring(with: range) linesArray.append(lineString as String) } return linesArray } }
如果你的所有angular色都以相同的尺寸显示,也就是说它们被封在一个通用尺寸的框中,你可以利用它。 (例如,对于日文字符,这似乎就是这种情况)。
否则,您可以查询显示字体中每个字符的大小,并计算该行必须是什么。
唯一的担心是,你的计算可能不同意苹果在幕后做的事 – 在这种情况下,我build议你去重写文本框架图的麻烦。 在这个文件中查找核心文本。
(我可能一直在做这个错误,但是我没有发现苹果在文档中提供的方法非常准确,所以我自己也做了一些其他的事情。)