问题
我需要了解TextKit的工作原理以及如何使用它来构建文本编辑器.我需要弄清楚如何仅绘制最终用户与之交互的可见文本,或者确定如何在不将属性应用于processEditing方法中的整个更改范围的文本的情况下懒惰地将属性应用于可见文本.
背景
iOS 7推出了TextKit.我有一个完全实现TextKit的tokenizer和代码(参考Apple的TextKitDemo项目 - 下面提供了一个链接)......它的工作原理.但是,它真的很慢.在通过NSTextStorage解析文本时,它要求您在processEditing方法中在同一线程上着色已编辑文本的ENTIRE范围.将工作卸载到线程没有帮助.这太慢了.我到了可以仅重新定义修改范围的点,但是如果范围太大,则过程将变慢.在某些情况下,整个文档可能会在更改后失效.
以下是我的一些想法.如果其中任何一个有用,或者可能在正确的方向上推动我,请告诉我.
1)多个NSTextContainers
阅读文档似乎我可以在NSLayoutManager中添加多个NSTextContainer.我假设通过这样做我不仅可以定义可以在NSTextContainer中绘制的行数,而且我还应该能够知道哪个NSTextContainer对最终用户可见.我知道,如果我走这条路,我需要投入大量时间才能看出它是否可行.初步测试表明您只需要一个NSTextContainer.所以我必须子类化NSLayout或创建一个包装器,布局管理器确定哪个文本进入哪个文本容器.呸.此外,我不知道TextKit如何让我知道是时候绘制一个特定的NSTextContainer ...也许这不是它的工作方式!
2)使用NSLayoutManager使范围无效
使用invalidateLayoutForCharacterRange:actualCharacterRange:使layoutManager无效.但这实际上做了什么以及如何卸载文本归属阶段?什么时候让我知道需要突出显示特定文本?另外,我看到NSLayoutManager会懒洋洋地绘制字形......怎么样?什么时候?这对我有什么帮助?如何点击此调用以便在实际布置文本之前我可以将支持字符串归属?
3)覆盖NSLayoutManager drawGlyphsForGlyphRange:atPoint:方法.
我真的不想这样做.话虽这么说,在Mac OS X中,NSAttributedStrings具有临时属性的概念,其中样式信息仅用于表示.这加快了突出显示的过程!问题是,它在iOS 7 TextKit框架中不存在(或者它就在那里,我只是不知道它).我相信通过覆盖这种方法,它会给我与使用临时属性所获得的相同类型的速度......因为我可以回答此方法中的所有布局,颜色和格式问题,而无需触及NSTextStorage归因串.唯一的问题是,我不知道这个方法如何与NSLayoutManager类中提供的其他方法相关.它是否保持宽度和高度的状态?当它太小时,它是否会修改NSTextContainer的大小?此外,它仅为已在文本缓冲区中添加的字符绘制字形.它不会重新绘制整个屏幕.它只是它的一小部分......而且非常好.我有一些关于如何使用它的想法...但我真的不想布置字形.这是太多的工作,我没有找到一个很好的例子来做到这一点.
非常感谢您提供的任何帮助.
谢谢你,我列出了过去几年我用过的所有框架和参考资料,这些框架和参考资料帮助我到达了现在的位置,希望它们对你有所帮助.
突出显示框架的语法:
资源:
大多数这些框架都是相同的.它们要么不考虑上下文切换(或者你必须编写包装器以提供上下文),要么它们不修复上下文范围,因为用户修改了文本(例如字符串,多行注释等).最后一项要求非常重要.因为如果标记生成器无法确定哪些范围受更改影响,则最终必须再次解析并归因整个字符串.唯一的例外是Crimson Editor.此标记化程序的问题是它在标记化时不保存状态.在绘制时,算法使用标记来确定绘图的状态.它从文档的顶部开始,直到达到可见的文本范围.不用说,
另一个问题是框架不遵循与Apple相同的MVC模式 - 这是预期的.具有完整工作编辑器的框架都使用由它们构建的API(即GTK,Windows等)提供的钩子,这些钩子为它们提供了绘制到屏幕的哪个部分的位置和时间的信息.在我的例子中,TextKit似乎要求您在processEditing中归因整个更改的范围.
也许我的观察是错误的.(我希望它们是!!)也许,ParseKit,例如,将适用于我需要它做什么,我只是不明白如何使用它.如果是这样,请告诉我!再次感谢!
我一直在为iOS 7重写我的应用程序.它现在使用新的TextKit API.我差不多完成了,但是还有一个问题让我头疼,因为我已经开始进行过渡了.
问题:当我在UITextView中输入文本时,视图会向上滚动以隐藏光标.很难确定模式,但它似乎发生在我删除一行后,下面的文字必须向上移动.但是只有第二次我删除了一行而且只删除了文档中的某些行(通常是只有换行符但不总是......的行)
我尝试在stackoverflow上使用这些解决方案:
插入每个新行后UITextView继续滚动,因此行不可见(iPhone OS)
还有许多其他问题,当在UITextView中使用UITableView时,滚动无法正常工作.我认为我没有表格视图.
我想指出我已经将UITextView子类化,并发现它绝对是iOS 7调用,不仅向上滚动视图.而且,更奇怪的是,当您按下后退按钮(从UITextView中删除一个字符)时,它会发送两条消息textViewDidChangeSelection:.发生问题时,这是调用堆栈.(当问题没有发生时,我仍然得到委托的两个调用textViewDidChangeSelection:......这似乎是正常的):
textViewDidChangeSelection:包含要删除的字符的位置,长度为1.(即1050,1)textViewDidChangeSelection:再次调用UITextView委托并包含相同的位置但长度为零.(即1050,0)UITextView.scrollRangeToVisible:w/FIRST调用的范围{1050,1}.这对我来说毫无意义.我知道这是在内部调用的,而不是来自我的任何代码,因为这个内部API被调用,_ensureselectionvisible无需追溯到我可能用来调用滚动事件的函数.据推测,前两个调用只是选择字符,然后在内部调用deleteBackwards.那讲得通.不过,我之后会失明.我不知道为什么它会滚动或为什么它会调用scrollRangeToVisible:WRONG范围.
通过在用户编辑文本时UITextView.scrollRangeToVisible:返回w/o调用[super scrollRangeToVisible],我已经能够通过覆盖来缓解这个问题.我这样做是通过覆盖一些scrollview委托调用并设置一个标志,表示不能进行滚动.对我来说,这是一个巨大的UGLY黑客,在某些情况下仍然会出现问题 - 比如当我在第一次编辑时进入视图,有时当滚动视图停止减速时.
简而言之,正在发生的是滚动事件发生(可能是由于前一行向上移动)而iOS由于某种原因认为光标不在视图中.更令人好奇的是,即使提供了错误的范围,它确实提供了正确的位置,然后将其滚动到视图中的错误位置.更令人好奇的是,它只发生在某些条件下,而只发生在条件发生的第二个实例中.我唯一能想到的是,在删除文本后,UITextView的高度无法正确计算,并且它认为文本位于与实际位置不同的位置.
提前致谢!
更新:
我设置了我之前谈到过的标志scrollViewDidScroll:,它不会阻止其他情况下的跳跃.但是,仍然存在向后删除文本仍会跳转到屏幕的情况.在视图仍然跳跃的情况下,更奇怪的是我发现我[super scrollRangeToVisible]无法被调用!因此,在ADDITION内部发生了一些事情,导致视图滚动.
更新:
它似乎在613点到670点之间跳跃.我不确定是什么导致了分数差异.它跳跃的行数也有所不同.我怀疑条件之间必须有类似的东西.此外,当scrollViewDidScroll:被调用时,我验证了textView.selectedRange.location此调用和委托textViewDidChangeSelection:调用之间的相同.
我有一个iOS应用程序,我想要做的就是提供更多支持基本命令键组合,如命令+ a,命令+ s,命令+ x,命令+ v和朋友,当用户连接蓝牙键盘时.
我知道这是可能的.Textastic等应用程序和许多其他编辑应用程序都支持这些功能.
我查看了UIResponder(它似乎只用于弹出菜单),UIKeyInput,UITextInput [Delegate]和其他API文档,但没有参考如何执行此操作.
这是很容易支持哪些选项是使用(BOOL)canPerformAction显示在UIMenuController:(SEL)动作withSender:(ID)发送者.但是,当连接蓝牙键盘时,似乎不会调用此方法.所以我要么专门为键盘或其他东西实现另一种方法.
我现在怀疑文本子系统可能负责执行操作.但是,没有我能找到的文件!此外,执行操作时不会调用任何UITextInput委托方法.我几乎认为解决方案是私有的,我需要特别询问Apple如何访问这些功能(我刚刚完成).
更新:
positionFromPosition:inDirection:offset:是用于检测何时按下箭头键的方法.在iOS调用此方法之后,它调用setSelectedText:.你需要解决剩下的管道问题.
更新2:
我能够回答所有问题.请参阅标记的解决方案以获取答案.