这是示例代码块
let attrString = NSAttributedString(string: "very long string goes here...") // very long string
var currentTextPos = 400 // current text position. ex. 400
let framesetter = CTFramesetterCreateWithAttributedString(attrString as CFAttributedString)
let path = CGPath(rect: UIScreen.main.bounds, transform: nil)
let ctFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(currentTextPos, 0), path, nil)
// draw frame with CTFrameDraw() function later
举个例子,假设我们有很长的属性字符串,我们想从 400 索引开始绘制一个帧。
要绘制下一帧,我们可以计算当前帧中有多少字符并绘制它。以下是如何实现它的示例:
// Get the length of string which fits in current CTFrame object
let frameLength = CTFrameGetVisibleStringRange(ctFrame).length // ex. frameLength == 95
// Append this to our currentTextPos variable
currentTextPos += frameLength // 400 + 95 = 495 . This is our next frame starting position
// Create another frame starting from 495 position
let nextFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(currentTextPos, 0), path, nil)
在这种情况下,我们能够获得下一个CTFrame
对象。这很容易实现,因为CTFramesetterCreateFrame
将用一条线填充整个帧,直到它到达帧的末尾或直到字符串的末尾。所以很容易获得下一个CTFrame
起始位置。
主要问题是如何获取先前的CTFrame
对象?还是之前的CTFrame
起始位置?
想象一下,我们只有当前的文本位置,没有别的。从字符串的开头到结尾分别计算每个帧的起始位置并将其缓存在某处也很容易,但是如果我们能够更改属性字符串字体大小或类似的东西,这将改变CTFrame
整个. 更改字体大小后,应从与更改字体大小CTFrame
之前相同的 currentTextPosition 绘制对象,换句话说,更改字体大小不应影响当前帧的起始位置。