由于某些字体具有可变宽度的字符,因此您无法在每种字体中获得固定数量的字符。您可以做的是尝试将字符串分成行大小的块:
extension String {
func split(width: CGFloat, font: UIFont) -> [String] {
guard !self.isEmpty else { return [String]() }
var lines = [String]()
// set up range of the split
var splitStart = self.startIndex
var splitEnd = self.startIndex
repeat {
// advance the end range for the split
splitEnd = self.index(after: splitStart)
// initial split to test
var line = String(characters[splitStart..<splitEnd])
// while we're before the end test the rendered width
while splitEnd < self.endIndex &&
line.size(attributes: [NSFontAttributeName: font]).width < width {
// add one more character
splitEnd = self.index(after: splitEnd)
line = String(characters[splitStart..<splitEnd])
}
// add split to array and set up next split
lines.append(line)
splitStart = splitEnd
} while splitEnd < self.endIndex // don't go past the end of the string
// add remainder of string to array
lines.append(String(characters[splitStart..<self.endIndex]))
return lines
}
}
这可以通过预先计算整个字符串的宽度,除以行数,从每行的平均宽度开始,然后尝试更多或更少的字符,直到它适合。但是,这确实使代码更加复杂。
如果您想确保单词不会被拆分,那么您可以保存每个单词的开头位置,当您到达行尾时,将拆分结束放在单词之前,将单词带到下一次分裂。当然,您还需要考虑太长而无法拆分的单词、连字词等等。
另一种方法是使用NSLayoutManager 和NSTextContainer,因为您需要更高级的布局:
let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Non est ista, inquam, Piso, magna dissensio. Minime vero istorum quidem, inquit. Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Negat enim summo bono afferre incrementum diem. Quasi ego id curem, quid ille aiat aut neget. Semper enim ex eo, quod maximas partes continet latissimeque funditur, tota res appellatur. Duo Reges: constructio interrete."
let font = UIFont.systemFont(ofSize: 24.0)
// set up styled text for the container
let storage = NSTextStorage(string: text, attributes: [NSFontAttributeName: font])
// add a layout manage for the storage
let layout = NSLayoutManager()
storage.addLayoutManager(layout)
// Set up the size of the container
// width is what we care about, height is maximum
let width:CGFloat = 500
let container = NSTextContainer(size: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude))
// add the container to the layout
layout.addTextContainer(container)
var lines = [String]()
// generate the layout and add each line to the array
layout.enumerateLineFragments(forGlyphRange: NSMakeRange(0, storage.length)) {
lines.append(storage.attributedSubstring(from: $0.3).string)
}
lines.forEach { print($0) }
结果:
Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Non est ista, inquam, Piso,
magna dissensio. Minime vero istorum
quidem, inquit. Graecum enim hunc versum
nostis omnes-: Suavis laborum est
praeteritorum memoria. Negat enim summo
bono afferre incrementum diem. Quasi ego id
curem, quid ille aiat aut neget. Semper enim
ex eo, quod maximas partes continet
latissimeque funditur, tota res appellatur. Duo
Reges: constructio interrete.
如果您愿意,您还可以通过NSLayoutManager 提供断字和其他行为。