Mac开发-NSTextView软回车转换为硬回车

2023-11-29 18:38

本文主要是介绍Mac开发-NSTextView软回车转换为硬回车,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景说明

软回车和硬回车:在字处理软件中,由Enter键按下去导致一行文字换行的叫硬回车,程序自动换行的叫做软回车。

当NSTextView的宽度被限制时,会自动换行,这里就是添加了软回车,当我们手动键入Enter,则是在字符串中插入了\n换行符,数据内容已经改变。软回车不会改变数据内容,即不会插入\n

需求为当NSTextView进行软回车时,记录下来,在某个时机发出其内容,并将软回车转换为硬回车,即在对应位置插入\n

TextKit

NSTextView的基础使用参考 https://blog.csdn.net/lovechris00/article/details/78014081

TextKit 框架主要的成员对象(典型的MVC):

  • NSTextStorage 是 NSMutableAttributedString 的子类,负责存储需要处理的文本及其属性。
  • NSLayoutManager 负责将 NSTextStorage 中的文本数据渲染到显示区域上,负责字符的编码和布局。
  • NSTextContainer 描述了一个显示区域,默认是矩形,其子类可以定义任意的形状。它不仅定义了可填充的区域,而且内部还定义了一个不可填充区域(Bezier Path 数组)。
    在这里插入图片描述
    参考这篇文章 https://www.jianshu.com/p/a12ecae89d6b 和 官方文档 中搜索。

即NSTextStorage负责文本内容,NSLayoutManager负责布局换行,字符处理,NSTextContainer负责显示的区域。
在我们使用NSTextView时,默认都会关联上述3个。监听软回车则需要监听到换行,或者每行所占字符数,即着重点在NSLayoutManager中。

解决方案

最初

layoutManager:shouldBreakLineByWordBeforeCharacterAtIndex方法是NSLayoutManager的代理方法,在文本改变时,会抛出软回车位置。

起初我想用这个回调,但发现layoutManager:shouldBreakLineByWordBeforeCharacterAtIndex在文本内容全是英文时,返回的软回车位置不对。
例如:

本应该软回车位置为 11 22 33 时
当中文时,返回为 11 22 33
当英文时,返回为 0  11 22 会缺少最后一位

这个回调当文本改变时就会回调。

最终方案

我又找到了一个可以计算出每行的字符长度的方法
即NSLayoutManager中的 enumerateLineFragmentsForGlyphRange

// Enumerates line fragments intersecting with glyphRange.
- (void)enumerateLineFragmentsForGlyphRange:(NSRange)glyphRange usingBlock:(void (^)(NSRect rect, NSRect usedRect, NSTextContainer *textContainer, NSRange glyphRange, BOOL *stop))block NS_AVAILABLE(10_11, 7_0);

这个方法需要主动调用,会在block块中返回每行的字符串范围。

参数说明如下

rect 预留给该行使用的大小
usedRect 实际该行使用的大小
textContainer 自己的textContainer实例
glyphRange 文本Range,由Postion和length组成。表示该行开始位置,以及长度

那我们就很好处理了,分别记录,然后从后向前插入\n即可

__weak typeof(self) wself = self;[_layoutManagerB enumerateLineFragmentsForGlyphRange:NSMakeRange(0, testString.length) usingBlock:^(NSRect rect, NSRect usedRect, NSTextContainer * _Nonnull textContainer, NSRange glyphRange, BOOL * _Nonnull stop) {__strong typeof(self) sself = wself;NSInteger index = glyphRange.location + glyphRange.length;[sself.breaklineIndexs addObject:@(index)];if (sself.layoutManagerB.numberOfGlyphs == index) { //因为最后一个字符后一定会插入\n,当字符数量==index时,即stopNSString *result = [self getBreaklineString];NSLog(@"添加硬回车后的字符串为 %@",result);*stop = YES;}}];

附上最终的demo,供大家参考

链接:https://pan.baidu.com/s/1-jgSF9IucvzzCRo0yun1HA 密码:3nc2

学习不断,有错误请指出,如果对你有帮助,请点个赞?

这篇关于Mac开发-NSTextView软回车转换为硬回车的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/433894

相关文章

C语言中的常见进制转换详解(从二进制到十六进制)

《C语言中的常见进制转换详解(从二进制到十六进制)》进制转换是计算机编程中的一个常见任务,特别是在处理低级别的数据操作时,C语言作为一门底层编程语言,在进制转换方面提供了灵活的操作方式,今天,我们将深... 目录1、进制基础2、C语言中的进制转换2.1 从十进制转换为其他进制十进制转二进制十进制转八进制十进

Pandas进行周期与时间戳转换的方法

《Pandas进行周期与时间戳转换的方法》本教程将深入讲解如何在pandas中使用to_period()和to_timestamp()方法,完成时间戳与周期之间的转换,并结合实际应用场景展示这些方法的... 目录to_period() 时间戳转周期基本操作应用示例to_timestamp() 周期转时间戳基

一文教你如何解决Python开发总是import出错的问题

《一文教你如何解决Python开发总是import出错的问题》经常朋友碰到Python开发的过程中import包报错的问题,所以本文将和大家介绍一下可编辑安装(EditableInstall)模式,可... 目录摘要1. 可编辑安装(Editable Install)模式到底在解决什么问题?2. 原理3.

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

Python+PyQt5开发一个Windows电脑启动项管理神器

《Python+PyQt5开发一个Windows电脑启动项管理神器》:本文主要介绍如何使用PyQt5开发一款颜值与功能并存的Windows启动项管理工具,不仅能查看/删除现有启动项,还能智能添加新... 目录开篇:为什么我们需要启动项管理工具功能全景图核心技术解析1. Windows注册表操作2. 启动文件

使用Python开发Markdown兼容公式格式转换工具

《使用Python开发Markdown兼容公式格式转换工具》在技术写作中我们经常遇到公式格式问题,例如MathML无法显示,LaTeX格式错乱等,所以本文我们将使用Python开发Markdown兼容... 目录一、工具背景二、环境配置(Windows 10/11)1. 创建conda环境2. 获取XSLT

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映