在没有 contentSize.height 的情况下获取 UITextView 中的行数

Get number of lines in UITextView without contentSize.height

我正在创建要在我的 iOS 应用中导出的图像。我正在使用 UIGraphicsBeginImageContext 来绘制图像的元素,但我一直在努力在图像中绘制 UITextView。

首先我创建一个用于渲染的父视图:

var parentView : UIView = UIView(frame: CGRectMake(0, 0, 700, 700))

然后我以编程方式创建 textView 并添加所有属性。我给它 x=100 和 y=100 来对齐图像中的文本。 width = 500 最好每边留出 100px 的边距:

var textView: UITextView = UITextView(frame: CGRectMake(100, 100, 500, 350))
textView.text = myText
textView.textContainerInset = UIEdgeInsetsMake(20, 20, 20, 20)
textView.backgroundColor = UIColor(red: 255, green: 255, blue: 255, alpha: 0.70)
textView.font = UIFont(name: "Helvetica Neue Light Italic", size: 35)

然后我通过将文本视图作为子视图添加到父视图来在上下文中渲染文本视图,然后获取要导出的图像:

parentView.addSubview(textView)        
parentView.layer.renderInContext(UIGraphicsGetCurrentContext())    
var newIMG = UIGraphicsGetImageFromCurrentImageContext()

问题是高度固定为 350px,但有时文本不够长,无法使用所有区域。理想情况下,我想知道我的文本将使用多少行,所以我可以给它一个比例高度并且没有白色未使用的区域(例如参见图片):

关于如何以比例高度呈现文本视图的任何想法?非常感谢!

我没有找到获取行数的方法,但我设法使用 textView.sizeToFit() 删除了所有白色 space。效果很好,希望有人会发现它有用!

我在 Apple Text Layout Programming Guide 中找到了这个问题的完美解决方案。 Apple提供的解决方案在Objective-C,所以我测试并重写了Swift。

这两种方法都很好用,而且 return UITextView 中使用的行数 准确,没有时髦的数学运算,每次都是 100% 准确。

这是我对 UITextView 添加 numberOfLines() 方法的扩展:

extension UITextView {
    func numberOfLines() -> Int {
        let layoutManager = self.layoutManager
        let numberOfGlyphs = layoutManager.numberOfGlyphs
        var lineRange: NSRange = NSMakeRange(0, 1)
        var index = 0
        var numberOfLines = 0

        while index < numberOfGlyphs {
            layoutManager.lineFragmentRectForGlyphAtIndex(
                index, effectiveRange: &lineRange
            )
            index = NSMaxRange(lineRange)
            numberOfLines += 1
        }
        return numberOfLines
    }
}

只需像这样直接在 UITextView 上调用它:myTextView.numberOfLines() <- returns an Int


这个扩展也很容易转换成这样的方法:

func numberOfLines(textView: UITextView) -> Int {
    let layoutManager = textView.layoutManager
    let numberOfGlyphs = layoutManager.numberOfGlyphs
    var lineRange: NSRange = NSMakeRange(0, 1)
    var index = 0
    var numberOfLines = 0

    while index < numberOfGlyphs {
        layoutManager.lineFragmentRectForGlyphAtIndex(index, effectiveRange: &lineRange)
        index = NSMaxRange(lineRange)
        numberOfLines += 1
    }
    return numberOfLines
}

只需调用numberOfLines(myTextView)获取行数的Int