Ios 如何使用正确的换行符在等边界视图中拆分NSAttributedString
我一直在努力解决这个问题。有一些API为我们提供了Ios 如何使用正确的换行符在等边界视图中拆分NSAttributedString,ios,string,range,nsattributedstring,core-text,Ios,String,Range,Nsattributedstring,Core Text,我一直在努力解决这个问题。有一些API为我们提供了nsattributestring的给定属性的边界大小 但是,并没有直接的方法可以获得适合给定范围的字符串范围 我的要求是在几个页面视图中放入很长的字符串(PDF不是选项,滚动也不是)。因此,我必须计算每个视图的字符串大小(相同的边界) 经过研究,我发现,ctframesetter建议frameSizeWithConstraints及其核心文本中的朋友可能会有所帮助。我尝试了这种方法,但结果范围有一个丑陋的问题: 它忽略了分词(这是一个与核心文本
nsattributestring
的给定属性的边界大小
但是,并没有直接的方法可以获得适合给定范围的字符串范围
我的要求是在几个页面视图中放入很长的字符串(PDF不是选项,滚动也不是)。因此,我必须计算每个视图的字符串大小(相同的边界)
经过研究,我发现,ctframesetter建议frameSizeWithConstraints
及其核心文本中的朋友可能会有所帮助。我尝试了这种方法,但结果范围有一个丑陋的问题:
它忽略了分词(这是一个与核心文本无关的不同问题,但我真的很想看看是否有解决方案)
基本上,我希望跨UITextView
对象的数量对文本进行分页,但不希望得到正确的属性字符串拆分
注意:
我的NSAttributedString
属性如下:
let attributes: [NSAttributedString.Key : Any] = [.foregroundColor : textColor, .font : font, .paragraphStyle : titleParagraphStyle]
(titleParagraphStyle
已将lineBreakMode
设置为byWordWrapping
)
扩展UITextView
{
func getStringSplits(fullString:String,attributes:[NSAttributedString.Key:Any])->[String]
{
让attributeString=NSAttributeString(string:fullString,attributes:attributes)
让frameSetterRef=CTFramesetterCreateWithAttributedString(attributeString作为CFAttributedString)
var initFitRange:CFRange=CFRangeMake(0,0)
var finalRange:CFRange=CFRangeMake(0,fullString.count)
变量范围:[Int]=[]
重复
{
CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef、initFitRange、属性如CFDictionary、CGSize(宽度:bounds.size.width、高度:bounds.size.height)和finalRange)
initFitRange.location+=finalRange.length
ranges.append(finalRange.length)
}
while(finalRange.location事实上,UITextView将自动将长文本从一个文本视图流向另一个文本视图。这只是配置文本工具包堆栈的问题—一个布局管理器和多个文本容器。+1谢谢。您知道它的任何示例链接吗?您的回答似乎表明我的方法有些过火。我缺少什么?案例1谢谢对于链接。我的问题实际上涉及任意数量的文本视图,具体取决于字符串长度。有没有一种方法可以根据文本范围创建任意数量的文本视图,并与您在链接中描述的共享相同的文本存储?我不知道有什么方法可以阻止它。听起来您正在编写一个读书应用程序,如Apple Books或Marv当然,这是一个解决得很好的问题。你的假设是正确的。问题是,我似乎无法将文本视图的创建与内容联系起来,也就是说,看看我的代码,它通过文本范围进行解析,为我提供适合每个页面的字符串数组。只是为了尝试,我遵循了你的2个文本视图的示例,但我看到空白的第2个文本视图,尽管它们共享相同的文本存储。
extension UITextView
{
func getStringSplits (fullString: String, attributes: [NSAttributedString.Key:Any]) -> [String]
{
let attributeString = NSAttributedString(string: fullString, attributes: attributes)
let frameSetterRef = CTFramesetterCreateWithAttributedString(attributeString as CFAttributedString)
var initFitRange:CFRange = CFRangeMake(0, 0)
var finalRange:CFRange = CFRangeMake(0, fullString.count)
var ranges: [Int] = []
repeat
{
CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef, initFitRange, attributes as CFDictionary, CGSize(width: bounds.size.width, height: bounds.size.height), &finalRange)
initFitRange.location += finalRange.length
ranges.append(finalRange.length)
}
while (finalRange.location < attributeString.string.count)
var stringSplits: [String] = []
var startIndex: String.Index = fullString.startIndex
for n in ranges
{
let endIndex = fullString.index(startIndex, offsetBy: n, limitedBy: fullString.endIndex) ?? fullString.endIndex
let theSubString = fullString[startIndex..<endIndex]
stringSplits.append(String(theSubString))
startIndex = endIndex
}
return stringSplits
}
}