获取UILabel中的每一行文本

时间:2017-10-25 02:36:43

标签: ios swift core-text

我试图将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?"]

但标签看起来像这样:

passed to the PromptChoice constructor

我希望得到["Hey there how\'s it ", "going today?"]。发生了什么事?

1 个答案:

答案 0 :(得分:4)

所以它似乎与UILabel有关,并且与您正在使用的功能没有任何问题。我怀疑CATextLayer会渲染它们从该方法返回的方式,我遗憾地发现:(我是对的。

以下是我的搜索结果: enter image description here

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

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

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

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上查看Core-Text-Label。它完全像CATextLayers那样呈现,并且与get行的返回相匹配。它不适用于我的特殊需求,因为我需要我的可调整大小并且它崩溃但是如果不需要调整大小那么我会检查它。

最后我又回来了,看起来这可能是在iOS 11中启动的自动换行问题,他们不会在行上留下孤儿字。