一部のフォントは、可変幅の文字を持っているので、あなたは、すべてのフォントでの行の文字のセット数を取得することはできません。あなたにできることはアップライン・サイズのチャンクに文字列を分割しようとする次のとおりです。
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
。
興味があるだけ。あなたはどんな種類のキャラクターを使用するかによってそれは違うでしょうか? 10の幅が10 Aより短いと言う... iiiiiiiiii:AAAAAAAAAA – sCha
はい。特定の文字列の何文字が1行に収まるかを知りたい。基本的には、行ごとに取得できる最大値に基づいて文字列を配列に分割する必要があります。最初のようなものがAAAAAなら...それはあまり適合しません。私はそれを計算することができる必要があります – user1079052
私はあなたが正しいレンダリングされた長さに合うように 'String'を分割したいと思っていますか?あなたはその質問を明確にしたいかもしれません。 – ColGraff