我正在尝试将UILabel中的每一行添加到数组中,但是我使用的代码似乎并不十分准确。

func getLinesArrayOfStringInLabel(label:UILabel) -> [String] {

    guard let text: NSString = label.text as? NSString else { return [] }
    let font:UIFont = label.font
    let rect:CGRect = label.frame

    let myFont: CTFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)

    let attStr:NSMutableAttributedString = NSMutableAttributedString(string: text as String)
    attStr.addAttribute(NSAttributedStringKey.font, value:myFont, range: NSMakeRange(0, attStr.length))

    let frameSetter:CTFramesetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString)

    let path: CGMutablePath = CGMutablePath()
    path.addRect(CGRect(x: 0, y: 0, width: rect.size.width, height: 100000))

    let frame:CTFrame = 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.substring(with: range)
        linesArray.append(lineString as String)
    }
    return linesArray
}


let label = UILabel()
label.numberOfLines = 0
label.frame = CGRect(x: 40, y: 237, width: 265, height: 53)
label.font = UIFont.systemFont(ofSize: 22, weight: UIFont.Weight.regular)
label.text = "Hey there how's it going today?"
label.backgroundColor = .red
bg.addSubview(label)
print(getLinesArrayOfStringInLabel(label: label))

此打印
["Hey there how\'s it going ", "today?"]

但是标签看起来像这样:

ios - 获取UILabel中的每一行文本-LMLPHP

我希望得到["Hey there how\'s it ", "going today?"]。这是怎么回事?

最佳答案

因此,这似乎与UILabel无关,而与您使用的函数无关。我怀疑CATextLayer会渲染这些行如何从该方法返回,我可悲的发现:(我是对的。

这是我的结果的图片:
ios - 获取UILabel中的每一行文本-LMLPHP

红色是您用来创建UILabel的确切代码。

绿色是CATextLayer,具有上面UILabel的所有相同特征,包括字体,字体大小和框架大小。

黄色是子类的UIView,它将替换自己的图层并返回CATextLayer。我将其附在下面。您可以继续构建它来满足您的需求,但是我认为这是真正的解决方案,并且唯一的解决方案是使获取行与用户看到的可见行相匹配。如果您提出更好的解决方案,请告诉我。

import UIKit

class AGLabel: UIView {

    var alignment : String = kCAAlignmentLeft{
        didSet{
            configureText()
        }
    }
    var font : UIFont = UIFont.systemFont(ofSize: 16){
        didSet{
            configureText()
        }
    }
    var fontSize : CGFloat = 16.0{
        didSet{
            configureText()
        }
    }
    var textColor : UIColor = UIColor.black{
        didSet{
            configureText()
        }
    }

    var text : String = ""{
        didSet{
            configureText()
        }
    }


    override class var layerClass: AnyClass {
        get {
            return CATextLayer.self
        }
    }

    func configureText(){
        if let textLayer = self.layer as? CATextLayer{
            textLayer.foregroundColor = textColor.cgColor
            textLayer.font = font
            textLayer.fontSize = fontSize
            textLayer.string = text
            textLayer.contentsScale = UIScreen.main.scale
            textLayer.contentsGravity = kCAGravityCenter
            textLayer.isWrapped = true
        }
    }
}

您还应该在GitHub上 checkout Core-Text-Label。它的呈现方式与CATextLayers完全相同,并且将与get行的返回值匹配。它不能满足我的特殊需求,因为我需要调整其大小,并且崩溃,但是如果不需要调整大小,那么我会检查一下。

最后,我又回来了,看来这可能是自动换行的问题,该问题始于iOS 11,在这种情况下,他们没有在行上留下孤立的单词。

10-08 07:45
查看更多