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) } }