iOS7中UITextView contentSize的变化和NSLayoutManager

2023-12-31

问题:UITextView默默地改变它contentSize在某些情况下。

最简单的情况是带有大文本和键盘的textView。只需添加 UITextView 出口并设置- viewDidLoad as:

- (void)viewDidLoad {
    [super viewDidLoad];
    // expand default "Lorem..."
    _textView.text = [NSString stringWithFormat:@"1%@\n\n2%@\n\n3%@\n\n4%@\n\n5", _textView.text, _textView.text, _textView.text, _textView.text];
    _textView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
    _textView.contentInset = UIEdgeInsetsMake(0, 0, 216, 0);
}

现在显示和隐藏键盘在某些情况下会导致文本跳转。

我找到了子类跳转的原因UITextView。我的子类中唯一的方法是:

- (void)setContentSize:(CGSize)contentSize {
    NSLog(@"CS: %@", NSStringFromCGSize(contentSize));
    [super setContentSize:contentSize];
}

它显示contentSize在键盘隐藏上缩小和扩展。像这样的事情:

013-09-16 14:40:27.305 textView-bug2[11087:a0b] CS: {320, 651}
2013-09-16 14:40:27.313 textView-bug2[11087:a0b] CS: {320, 885}
2013-09-16 14:40:27.318 textView-bug2[11087:a0b] CS: {320, 902}

看起来像的行为UITextViewiOS7中发生了很大的变化。有些东西现在已经坏了。

进一步发现我发现了新的layoutManager我的 textView 的属性也发生了变化。现在日志中有一些有趣的信息:

2013-09-16 14:41:59.352 textView-bug2[11115:a0b] CS: {320, 668}
<NSLayoutManager: 0x899e800>
    1 containers, text backing has 2129 characters
    Currently holding 2129 glyphs.
    Glyph tree contents:  2129 characters, 2129 glyphs, 3 nodes, 96 node bytes, 5440 storage bytes, 5536 total bytes, 2.60 bytes per character, 2.60 bytes per glyph
    Layout tree contents:  2129 characters, 2129 glyphs, 532 laid glyphs, 13 laid line fragments, 4 nodes, 128 node bytes, 1048 storage bytes, 1176 total bytes, 0.55 bytes per character, 0.55 bytes per glyph, 40.92 laid glyphs per laid line fragment, 90.46 bytes per laid line fragment

下一行内容为 contentSize ={320, 885}包含Layout tree contents: ..., 2127 laid glyphs, 51 laid line fragments。因此,看起来某种自动布局尝试在键盘显示上重新布局 textView 并更改 contentSize,即使布局尚未完成。即使我的 textView 在键盘显示/隐藏之间没有变化,它也会运行。

问题是:如何防止contentSize改变?


看起来问题出在默认的layoutManager中UITextView。我决定对其进行子类化,并查看在何处以及为何启动重新布局。但简单的创建NSLayoutManager使用默认设置解决了这个问题。

这是我的演示项目中的代码(不完美)(参见问题)。这_textView有一个插座,所以我将其从超级视图中删除。这段代码被放置在- viewDidLoad:

NSTextStorage* textStorage = [[NSTextStorage alloc] initWithString:_textView.text];
NSLayoutManager* layoutManager = [NSLayoutManager new];
[textStorage addLayoutManager:layoutManager];
_textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size];
[layoutManager addTextContainer:_textContainer];
[_textView removeFromSuperview];    // remove original textView
_textView = [[MyTextView alloc] initWithFrame:self.view.bounds 
                                textContainer:_textContainer];
[self.view addSubview:_textView];

MyTextView这是一个子类UITextView,请参阅问题了解详细信息。

欲了解更多信息,请参阅:

  • 关于 iOS 中的文本处理 https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/Introduction/Introduction.html
  • 使用 Text Kit 绘制和管理文本 https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/CustomTextProcessing/CustomTextProcessing.html#//apple_ref/doc/uid/TP40009542-CH4-SW1
  • iOS 的 NSLayoutManager 类参考 https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSLayoutManager_Class_TextKit/Reference/Reference.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS7中UITextView contentSize的变化和NSLayoutManager 的相关文章

随机推荐

  • 在片段中使用上下文的最佳方式

    我在我的应用程序中使用片段 我创建了一个名为 BaseFragment 的父类 所有其他片段都扩展了此 Basefrgment 下面是此 Basefragment 的片段 基础片段 java public class BaseFragmen
  • 更新 Python Pickle 对象

    我正在做一个机器学习项目 为此我正在使用picklePython 的模块 基本上 我正在解析一个巨大的数据集 这在一次执行中是不可能的 这就是为什么我需要保存分类器对象并在下一次执行中更新它 所以我的问题是 当我使用新数据集再次运行程序时
  • 将观察结果与重叠日期相结合

    我的数据框中的每个观察结果都包含不同的 日期之前 和 日期之后实例 问题是每个 ID 的某些日期重叠 例如 在下表中 ID 1 和 4 包含重叠的日期值 ID before date after date 1 10 1 1996 12 1
  • SimpleCursorAdapter 在 API 版本 15 中已弃用?

    简单光标适配器使用以下注释弃用其构造函数之一 已弃用 不鼓励使用此选项 因为它会导致在应用程序的 UI 线程上执行游标查询 从而导致响应能力差甚至应用程序无响应错误 作为替代方案 将 android app LoaderManager 与
  • AttributeError:“str”对象没有属性“policy”

    我是Python新手 我正在尝试制作一个可以发送电子邮件的电子邮件脚本 首先 我制作了一个没有任何类的 Python 脚本 只是运行以确保脚本按预期运行 当我得到预期的结果后 我正在尝试使用类重写脚本 以便学习 但我收到错误 我不明白 我不
  • 将导航属性映射到主表

    我有课Contract有两个属性TotalAmount and InstallmentAmount public class Contract public int ContractId get set public Amount Tota
  • fork调用后的地址空间

    当进程执行 fork 系统调用时 会生成一个子进程 fork 调用之后的所有代码都被复制到新的内存物理页 即帧 我无法可视化子进程的虚拟内存部分 因为在下面的代码中 char 变量的地址在子进程和父进程中是相同的 include
  • 为什么要使用 Android 服务?

    我想知道当您需要做很多事情只是为了访问任何公共方法或从服务 例如较大的 List 对象 获取大量数据时 使用 Android 服务进行后台工作有什么意义 如果您愿意 为什么不直接使用一个简单的 POJO 它可以在单独的线程中在后台为您执行操
  • 无法解析 rxjava 2 中的 Observable.from 方法

    rxjava 1 中的 Observable 类中有一个 from 方法 但在 rxjava 2 中找不到 如何在以下代码中替换 rxjava 2 中的 from 方法 List
  • 傀儡节点主机名

    我正在使用木偶来配置服务器 我想在 erb 模板中打印当前机器 节点 名称 有hostname变量 但这包含 puppetmaster 主机名 关于这个主题有什么好的参考 列表吗 好像我错过了什么地方 我只需在 erb 模板中调用以下代码即
  • 在 Django 的 ORM 中访问存储过程的最佳方式是什么

    我正在设计一个相当复杂的数据库 并且知道我的一些查询将远远超出 Django ORM 的范围 有人成功地将 SP 与 Django 的 ORM 集成吗 如果是这样 什么 RDBMS 以及您是如何做到的 我们 musicpictures co
  • iPhone 版 Mapsforge 模拟

    我的 iPhone 应用程序需要一些框架 该应用程序使用地图 现在这些地图是光栅图像 我想通过制作矢量地图来优化我的应用程序 我知道我的 Android 开发同事已经使用 Mapsforge 框架来实现此目的 iPhone 上有类似的库吗
  • 为什么我们在查找素数时可以使用 sqrt(n) 而不是 n/2 作为上限? [复制]

    这个问题在这里已经有答案了 我们如何使用sqrt n 代替n 2在这段代码中 使用是否正确sqrt n static boolean isPrime long n if n lt 1 return false double limit Ma
  • 使用curses.h从键盘获取字符

    我正在尝试使用curses h 从键盘获取一个字符 这是我的来源 get char example c include
  • 为什么位域的类型会影响包含结构的大小?

    首先 这是 ISO C 标准关于位字段的规定 引用了N1570 http www open std org jtc1 sc22 wg14 www docs n1570 pdf2011 年 ISO C 标准草案 第 6 7 2 1 节 位字段
  • 为什么允许“src”属性链接到来自外部域的脚本,而 XmlHtppRequests 则不允许?

    我已经阅读了 StackOverflow 上有关同源策略的几个答案 但我似乎没有抓住本质部分 在所有使用的标签中src属性 比如
  • 如何在 django 1.3 中获取 POST 数据

    嘿 我正在按照本教程学习使用 Django 制作 wiki 页面 然而 它是用 django 0 96 制作的 而我使用 Django 1 3 所以有些东西是不同的 有些我已经自己修好了 但是这个我似乎无法让它发挥作用 我制作了一个将数据提
  • javascript:将 元素保存到磁盘上的文件

    在我的 HTML 上 我有一个 SVG 元素 它使用 d3js 渲染并在 CSS 中应用样式 当我右键单击浏览器时 我可以选择 保存图像 此操作将保存应用所有 CSS 样式呈现的图像 我一直在寻找保存文件的好方法 转到画布并导出画布 可另存
  • AVAudioPlayer.play() 不播放声音

    为什么下面的代码不播放声音 它为 play 返回 true 但我听不到任何声音 let path Users account Music sound mp3 let fileURL NSURL fileURLWithPath path va
  • iOS7中UITextView contentSize的变化和NSLayoutManager

    问题 UITextView默默地改变它contentSize在某些情况下 最简单的情况是带有大文本和键盘的textView 只需添加 UITextView 出口并设置 viewDidLoad as void viewDidLoad supe