TextKit
推荐这种,计算较为准确,效率也较高。
func calculatedBookPages(byContent content: String) -> [String] {
let config = configuration
let dimension = config.dimension
func slicedText(from: Int, length: Int) -> String {
var len = length
let remainder = content.count - from
if length > remainder {
len = remainder
}
return content.slicing(from: from, length: len) ?? "Slicing Error"
}
var pagedTexts: [String] = []
let attrText = attributedBookContent("我")
let storage = NSTextStorage(string: content, attributes: attrText.attributes)
let layoutManager = NSLayoutManager()
storage.addLayoutManager(layoutManager)
while true {
let container = NSTextContainer(size: dimension.contentSize)
container.lineBreakMode = .byWordWrapping
container.lineFragmentPadding = 0
layoutManager.addTextContainer(container)
let range = layoutManager.glyphRange(for: container)
if range.length <= 0 {
break
}
pagedTexts.append(slicedText(from: range.location, length: range.length))
}
return pagedTexts
}
extension NSAttributedString {
typealias ParagraphStyle = (NSMutableParagraphStyle)->Void
static func with(text: String,
font: UIFont? = Font.System.p14,
color: UIColor? = Color.black_2B2D42,
paragraph: ParagraphStyle? = nil,
attrs: [Key: Any]? = nil) -> NSAttributedString
{
var attributes: [Key: Any] = [:]
if let handler = paragraph {
let pg = NSMutableParagraphStyle()
handler(pg)
attributes[Key.paragraphStyle] = pg
}
if let font = font {
attributes[Key.font] = font
}
if let color = color {
attributes[Key.foregroundColor] = color
}
if let attrs = attrs {
attrs.forEach {
attributes[$0] = $1
}
}
return .init(string: text, attributes: attributes)
}
}
func attributedBookContent(_ text: String) -> NSAttributedString {
let config = configuration
return .with(text: text, font: config.font.uiFont, color: config.color.textColor, paragraph: {
$0.lineHeightMultiple = config.paragraph.lineHeight
$0.paragraphSpacingBefore = config.font.size
}, attrs: [
NSAttributedString.Key.kern: config.paragraph.wordSpacing
])
}
加法
{
let length = content.count
var idx = 0
while true
{
if endIdx >= (length-beginIdx) {
endIdx -= 1
pagedTexts.append(rangedText)
break
}
var subText = rangedText
let attrText = attributedBookContent(byText: subText)
let size = attrText.boundingRect(with: .init(width: W, height: .infinity), options: [.usesFontLeading, .usesLineFragmentOrigin], context: nil).size
let h = size.height
if h >= H {
endIdx -= 1
subText = rangedText
pagedTexts.append(subText)
beginIdx = idx
endIdx = 1
}
else{
idx += 1
endIdx += 1
}
}
print("calculate end : \(Date().timeIntervalSince1970)")
return pagedTexts
}
减法
func calculatedBookPages(byContent content: String) -> [String] {
let config = configuration
let dimension = config.dimension
let W = dimension.contentSize.width
let H = dimension.contentSize.height
print("calculate begin : \(Date().timeIntervalSince1970)")
let text = attributedBookContent(byText: "中")
let pointSize = text.yy_font!.pointSize
let h = text.yy_lineHeightMultiple * pointSize
let w = pointSize + CGFloat(text.yy_kern!.floatValue) * Lets.screenScale
let count = content.count
func slicedText(from: Int, length: Int) -> String {
var len = length
let remainder = content.count - from
if length > remainder {
len = remainder
}
return content.slicing(from: from, length: len) ?? "Slicing Error"
}
var pagedTexts: [String] = []
var begin = 0
let colums = Int(W / w)
let lines = Int(ceil(H / h))
let pageLength = colums * lines
var stepLength = pageLength
var subText = ""
while true {
subText = slicedText(from: begin, length: stepLength)
let label = Label()
label.attributedText = attributedBookContent(byText: subText)
let height = label.sizeThatFits(.init(width: W, height: .infinity)).height
if height > H {
stepLength -= 1
}
else {
begin += stepLength
pagedTexts.append(subText)
stepLength = pageLength
}
if begin >= count {
break
}
}
return pagedTexts
}
网友评论