【发布时间】:2019-08-11 07:08:24
【问题描述】:
我正在尝试实现一个非常简单的文本编辑器,它既可以在 macOS 上使用 NSTextView,在 iOS 上也可以使用 UITextView。此文本编辑器有一个工具栏按钮“Section Break”,每次单击时都会在当前光标位置插入一个新部分。一个部分应该是:
视觉上可识别作为一个部分(通过在两个后续部分之间添加视觉分隔符并可能添加一些垂直空白),
可参考。用户应该能够在编辑器中看到所有部分的列表,并且通过单击该列表中的项目,文本视图应该立即滚动到该部分的开头。
在another question 中,我询问了如何解决第一个问题,不幸的是,我还没有找到这部分的答案(尽管有 solution that works on macOS only)。
但是,这个问题关注第二方面:
如何在我的文本视图中维护所有部分的列表,其中每个部分都保持对相关文本的准确引用?
这项任务的复杂性在于用户可以随时复制和粘贴或简单地编辑文本的任何部分。因此,我不能保留一个简单的段落编号数组或类似的东西。
我尝试了什么以及为什么这似乎是一项艰巨的任务:
-
我的一个想法是继承
NSTextStorage并使用可变属性字符串数组作为其内部存储。然后,我将使用NSTextAttachment的一个特殊子类,并将其用作我的文本存储中的分节指示符。问题在于the text view only calls the following methods whenever the user edits text:func replaceCharacters(in range: NSRange, with str: String)和
func setAttributes(_ attrs: [NSAttributedString.Key : Any]?, range: NSRange)第一种方法只传递没有任何属性的纯字符串,第二种方法只获取属性。这意味着在第一种方法中,我无法判断替换字符是否实际上应该是分节符,因此我无法决定在我的内部文本存储数组中的哪个位置创建新元素。
在第二种方法中,我不知道用户是否真的添加了新文本(在这种情况下,我必须在我的文本存储数组中为每个分节符属性添加一个新元素)或者用户是否只是更改了一些现有文本的属性(在这种情况下,之前已经创建了新的数组元素)。
我还考虑过在表格视图或堆栈视图中使用多个文本视图的想法。但是,这不起作用,因为它会阻止用户在多个后续部分中选择(和删除)文本。
最后,我尝试了子类化
NSLayoutManager,但是关于它的文档真的很薄,对我来说似乎是错误的地方。 (毕竟布局管理器的职责是文本的布局,而不是跟踪它的结构。)
有什么想法吗?
【问题讨论】:
标签: ios uitextview nstextview nslayoutmanager nstextstorage