如果启用了自动字体大小调整,则另一种方法是这样的:
let stringLength: Int = countElements(self.attributedText!.string)
let substring = (self.attributedText!.string as NSString).substringWithRange(substringRange)
if (substringRange.location + substringRange.length > stringLength)
{
return CGRectZero
}
let textRect: CGRect = self.textRectForBounds(self.bounds, limitedToNumberOfLines: self.numberOfLines)
let path: CGMutablePathRef = CGPathCreateMutable()
CGPathAddRect(path, nil, textRect)
let framesetter = CTFramesetterCreateWithAttributedString(self.attributedText)
let tempFrame: CTFrameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, stringLength), path, nil)
if (CFArrayGetCount(CTFrameGetLines(tempFrame)) == 0)
{
return CGRectZero
}
let lines: CFArrayRef = CTFrameGetLines(tempFrame)
let numberOfLines: Int = self.numberOfLines > 0 ? min(self.numberOfLines, CFArrayGetCount(lines)) : CFArrayGetCount(lines)
if (numberOfLines == 0)
{
return CGRectZero
}
var returnRect: CGRect = CGRectZero
let nsLinesArray: NSArray = CTFrameGetLines(tempFrame)
let ctLinesArray = nsLinesArray as Array
var lineOriginsArray = [CGPoint](count:ctLinesArray.count, repeatedValue: CGPointZero)
CTFrameGetLineOrigins(tempFrame, CFRangeMake(0, numberOfLines), &lineOriginsArray)
for (var lineIndex: CFIndex = 0; lineIndex < numberOfLines; lineIndex++)
{
let lineOrigin: CGPoint = lineOriginsArray[lineIndex]
let line: CTLineRef = unsafeBitCast(CFArrayGetValueAtIndex(lines, lineIndex), CTLineRef.self)
let lineRange: CFRange = CTLineGetStringRange(line)
if ((lineRange.location <= substringRange.location) && (lineRange.location + lineRange.length >= substringRange.location + substringRange.length))
{
var charIndex: CFIndex = substringRange.location - lineRange.location;
var secondary: CGFloat = 0.0
let xOffset: CGFloat = CTLineGetOffsetForStringIndex(line, charIndex, &secondary);
var ascent: CGFloat = 0.0
var descent: CGFloat = 0.0
var leading: CGFloat = 0.0
let width: Double = CTLineGetTypographicBounds(line, &ascent, &descent, &leading)
let yMin: CGFloat = floor(lineOrigin.y - descent);
let yMax: CGFloat = ceil(lineOrigin.y + ascent);
let yOffset: CGFloat = ((yMax - yMin) * CGFloat(lineIndex))
returnRect = (substring as NSString).boundingRect(with: CGSize(width: Double.greatestFiniteMagnitude, height: Double.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [.font: self.font ?? UIFont.systemFont(ofSize: 1)], context: nil)
returnRect.origin.x = xOffset + self.frame.origin.x
returnRect.origin.y = yOffset + self.frame.origin.y + ((self.frame.size.height - textRect.size.height) / 2)
break
}
}
return returnRect