import UIKit
import CoreText
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print(UIFont.familyNames)
let font = UIFont(name: "Heiti SC", size: 18)
let textStr = "Hi, I'm lilei, what's your name please? Are you Han Meimei?"
let label = UILabel(frame: CGRect(x: 10, y: 30, width: 100, height: 400))
self.view.addSubview(label)
label.font = font
label.numberOfLines = 0
label.text = textStr
print(getLines(text: textStr, font: font! , rect: CGRect(x: 10, y: 30, width: 100, height: 400)))
}
func getLines(text: String, font: UIFont, rect:CGRect) -> [String] {
let fontName: CFString = font.fontName as CFString
let myFont = CTFontCreateWithName(fontName, font.pointSize, nil)
let attStr = NSMutableAttributedString(string: text)
attStr.addAttribute(kCTFontAttributeName as NSAttributedString.Key, value: myFont, range: NSMakeRange(0, attStr.length))
let frameSetter: CTFramesetter = CTFramesetterCreateWithAttributedString(attStr)
let path: CGMutablePath = CGMutablePath()
path.addRect(CGRect(x: 0, y: 0, width: rect.size.width, height: CGFloat.greatestFiniteMagnitude))
let frame: CTFrame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)
let lines = CTFrameGetLines(frame) as Array
var linesArray = [String]()
for line in lines {
let lineRef: CTLine = line as! CTLine
let lineRange: CFRange = CTLineGetStringRange(lineRef)
let range: NSRange = NSMakeRange(lineRange.location, lineRange.length)
let subStr = text.substring(from: range.location, length: range.length)
linesArray.append(subStr)
}
return linesArray
}
}
extension String {
func substring(from: Int?, to: Int?) -> String {
if let start = from {
guard start < self.characters.count else {
return ""
}
}
if let end = to {
guard end >= 0 else {
return ""
}
}
if let start = from, let end = to {
guard end - start >= 0 else {
return ""
}
}
let startIndex: String.Index
if let start = from, start >= 0 {
startIndex = self.index(self.startIndex, offsetBy: start)
} else {
startIndex = self.startIndex
}
let endIndex: String.Index
if let end = to, end >= 0, end < self.characters.count {
endIndex = self.index(self.startIndex, offsetBy: end + 1)
} else {
endIndex = self.endIndex
}
return String(self[startIndex ..< endIndex])
}
func substring(from: Int) -> String {
return self.substring(from: from, to: nil)
}
func substring(to: Int) -> String {
return self.substring(from: nil, to: to)
}
func substring(from: Int?, length: Int) -> String {
guard length > 0 else {
return ""
}
let end: Int
if let start = from, start > 0 {
end = start + length - 1
} else {
end = length - 1
}
return self.substring(from: from, to: end)
}
func substring(length: Int, to: Int?) -> String {
guard let end = to, end > 0, length > 0 else {
return ""
}
let start: Int
if let end = to, end - length > 0 {
start = end - length + 1
} else {
start = 0
}
return self.substring(from: start, to: to)
}
}