iOS/Swift:深入理解iOS CoreText API

news/2025/10/19 21:45:11/文章来源:https://www.cnblogs.com/Con-Tch-LLYF/p/19151483

iOS/Swift:深入理解iOS CoreText API

这篇文章是从0到1自定义富文本渲染的原理篇之一,此外你还可能感兴趣:

  • 一文读懂字符与编码
  • 一文读懂字符、字形、字体
  • 一文读懂字体文件
  • 从0到1自定义文字排版引擎:原理篇
  • 逆向分析CoreText中的字体级联/Font Fallback机制
  • 新手小白也能看懂的LLDB技巧/逆向技巧

更多内容可订阅公众号「非专业程序员Ping」,文中所有代码可在公众号后台回复 “CoreText” 获取。

一、引言

CoreText是iOS/macOS中的文字排版引擎,提供了一系列对文本精确操作的API;UIKit中UILabel、UITextView等文本组件底层都是基于CoreText的,可以看官方提供的层级图:

在这里插入图片描述
本文的目的是结合实际使用例子,来介绍和总结CoreText中的重要概念和API。

二、重要概念

CoreText中有几个重要概念:CTTypesetter、CTFramesetter、CTFrame、CTLine、CTRun;它们之间的关系可以看官方提供的层级图:

在这里插入图片描述

一篇文档可以分为:文档 -> 段落 -> 段落中的行 -> 行中的文字,类似的,CoreText也是按这个结构来组织和管理API的,我们也可以根据诉求来选择不同层级的API。

2.1 CTFramesetter

CTFramesetter类似于文档的概念,它负责将多段文本进行排版,管理多个段落(CTFrame)。

CTFramesetter的输入是属性字符串(NSAttributedString)和路径(CGPath),负责将文本在指定路径上进行排版。

2.2 CTFrame

CTFrame类似于段落的概念,其中包含了若干行(CTLine)以及对应行的位置、方向、行间距等信息。

2.3 CTLine

CTLine类似于行的概念,其中包含了若干个字形(CTRun)以及对应字形的位置等信息。

2.4 CTRun

需要注意CTRun不是单个的字符,而是一段连续的且具有相同属性(字体、颜色等)的字形(Glyph)。

如下,每个虚线框都代表一个CTRun:

在这里插入图片描述

2.5 CTTypesetter

CTTypesetter支持对属性字符串进行换行,可以通过CTTypesetter来自定义换行(比如按word换行、按char换行等)或控制每行的内容,可以理解成更精细化的控制。

三、重要API

3.1 CTFramesetter

1)CTFramesetterCreateWithAttributedString

func CTFramesetterCreateWithAttributedString(_ attrString: CFAttributedString) -> CTFramesetter

通过属性字符串来创建CTFramesetter。

我们可以构造不同字体、颜色、大小的属性字符串,然后从属性字符串构造CTFramesetter,之后可以继续往下拆分得到段落、行、字形等信息,这样可以实现自定义排版、图文混排等复杂富文本样式。

2)CTFramesetterCreateWithTypesetter

func CTFramesetterCreateWithTypesetter(_ typesetter: CTTypesetter) -> CTFramesetter

通过CTTypesetter来创建CTFramesetter,当我们需要对文本实现更精细控制,比如自定义换行时,可以自己构造CTTypesetter。

3)CTFramesetterCreateFrame

func CTFramesetterCreateFrame(_ framesetter: CTFramesetter,_ stringRange: CFRange,_ path: CGPath,_ frameAttributes: CFDictionary?
) -> CTFrame

生成CTFrame:在指定路径(path)为属性字符串的指定范围(stringRange)生成CTFrame。

  • framesetter
  • stringRange:字符范围,注意需要以UTF-16编码格式计算;当 stringRange.length = 0 时,表示从起点(stringRange.location)到字符结束为止;比如当 CFRangeMake(0, 0) 表示全字符范围
  • path:排版路径,可以是不规则矩形,这意味着可以传入不规则图形来实现文字环绕等高级效果
  • frameAttributes:一个可选的字典,可以用于控制段落级别的布局行为,比如行间距等,一般用不到,可传 nil

4)CTFramesetterSuggestFrameSizeWithConstraints

func CTFramesetterSuggestFrameSizeWithConstraints(_ framesetter: CTFramesetter,_ stringRange: CFRange,_ frameAttributes: CFDictionary?,_ constraints: CGSize,_ fitRange: UnsafeMutablePointer<CFRange>?
) -> CGSize

计算文本宽高:在给定约束尺寸(constraints)下计算文本范围(stringRange)的实际宽高。

如下,我们可以计算出在宽高 100 x 100 的范围内排版,实际能放下的文本范围(fitRange)以及实际的文本尺寸:

let attr = NSAttributedString(string: "这是一段测试文本,通过调用CTFramesetterSuggestFrameSizeWithConstraints来计算文本的宽高信息,并返回实际的range", attributes: [.font: UIFont.systemFont(ofSize: 16),.foregroundColor: UIColor.black
])
let framesetter = CTFramesetterCreateWithAttributedString(attr)
var fitRange = CFRange(location: 0, length: 0)
let size = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,CFRangeMake(0, 0),nil,CGSize(width: 100, height: 100),&fitRange
)
print(size, fitRange, attr.length)

这个API在分页时非常有用,比如微信读书的翻页效果,需要知道在哪个地方截断,PDF的分页排版等。

3.1.1 CTFramesetter使用示例

1)实现一个支持AutoLayout且高度靠内容撑开的富文本View

在这里插入图片描述

2)在圆形路径中绘制文本

在这里插入图片描述

3)文本分页:模拟微信读书的分页逻辑
在这里插入图片描述

3.2 CTFrame

1)CTFramesetterCreateFrame

func CTFramesetterCreateFrame(_ framesetter: CTFramesetter,_ stringRange: CFRange,_ path: CGPath,_ frameAttributes: CFDictionary?
) -> CTFrame

创建CTFrame,在CTFramesetter一节中有介绍过,这是创建CTFrame的唯一方式。

2)CTFrameGetStringRange

func CTFrameGetStringRange(_ frame: CTFrame) -> CFRange

获取CTFrame包含的字符范围。

我们在调用CTFramesetterCreateFrame创建CTFrame时,会传入一个 stringRange 的参数,CTFrameGetStringRange也可以理解成获取这个 stringRange,区别是处理了当 stringRange.length 为0的情况。

3)CTFrameGetVisibleStringRange

func CTFrameGetVisibleStringRange(_ frame: CTFrame) -> CFRange

获取CTFrame实际可见的字符范围。

我们在调用CTFramesetterCreateFrame创建CTFrame时,会传入path,可能会把字符截断,CTFrameGetVisibleStringRange返回的就是可见的字符范围。

需要注意和CTFrameGetStringRange进行区分,可以用如下Demo验证:

let longText = String(repeating: "这是一个分栏布局的例子。Core Text 允许我们将一个长的属性字符串(CFAttributedString)流动到多个不同的路径(CGPath)中。我们只需要创建一个 CTFramesetter,然后循环调用 CTFramesetterCreateFrame。每次调用后,我们使用 CTFrameGetStringRange 来找出有多少文本被排入了当前的框架,然后将下一个框架的起始索引设置为这个范围的末尾。 ", count: 10)
let attributedText = NSAttributedString(string: longText, attributes: [.font: UIFont.systemFont(ofSize: 12),.foregroundColor: UIColor.darkText
])
let framesetter = CTFramesetterCreateWithAttributedString(attributedText as CFAttributedString)
let path = CGPath(rect: .init(x: 10, y: 100, width: 400, height: 200), transform: nil)
let frame = CTFramesetterCreateFrame(framesetter,CFRange(location: 100, length: 0),path,nil
)
// 输出:CFRange(location: 100, length: 1980)
print(CTFrameGetStringRange(frame))
// 输出:CFRange(location: 100, length: 584)
print(CTFrameGetVisibleStringRange(frame))

4)CTFrameGetPath

func CTFrameGetPath(_ frame: CTFrame) -> CGPath

获取创建CTFrame时传入的path。

5)CTFrameGetLines

func CTFrameGetLines(_ frame: CTFrame) -> CFArray

获取CTFrame中所有的行(CTLine)。

6)CTFrameGetLineOrigins

func CTFrameGetLineOrigins(_ frame: CTFrame,_ range: CFRange,_ origins: UnsafeMutablePointer<CGPoint>
)

获取每一行的起点坐标。

用法示例:

let lines = CTFrameGetLines(frame) as! [CTLine]
var origins = [CGPoint](repeating: .zero, count: lines.count)
CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), &origins)

7)CTFrameDraw

func CTFrameDraw(_ frame: CTFrame,_ context: CGContext
)

绘制CTFrame。

3.2.1 CTFrame使用示例

1)绘制CTFrame

在这里插入图片描述

2)高亮某一行

在这里插入图片描述

3)检测点击字符

在这里插入图片描述

3.3 CTLine

1)CTLineCreateWithAttributedString

func CTLineCreateWithAttributedString(_ attrString: CFAttributedString) -> CTLine

从属性字符串创建单行CTLine,如果字符串中有换行符(\n)的话,换行符会被转换成空格,如下:

let line = CTLineCreateWithAttributedString(NSAttributedString(string: "Hello CoreText\nWorld", attributes: [.font: UIFont.systemFont(ofSize: 16)])
)

2)CTLineCreateTruncatedLine

func CTLineCreateTruncatedLine(_ line: CTLine,_ width: Double,_ truncationType: CTLineTruncationType,_ truncationToken: CTLine?
) -> CTLine?

创建一个被截断的新行。

  • line:待截断的行
  • width:在多少宽度截断
  • truncationType:start/end/middle,截断类型
  • truncationToken:在截断处添加的字符,nil表示不添加,一般使用省略符(...)
let truncationToken = CTLineCreateWithAttributedString(NSAttributedString(string: "…", attributes: [.font: UIFont.systemFont(ofSize: 16)])
)
let truncated = CTLineCreateTruncatedLine(line, 100, .end, truncationToken)

3)CTLineCreateJustifiedLine

func CTLineCreateJustifiedLine(_ line: CTLine,_ justificationFactor: CGFloat,_ justificationWidth: Double
) -> CTLine?

创建一个两端对齐的新行,类似书籍或报纸中两端对齐的排版效果。

  • line:原始行
  • justificationFactorjustificationFactor <= 0表示不缩放,即与原始行相同;justificationFactor >= 1表示完全缩放到指定宽度;0 < justificationFactor < 1表示部分缩放到指定宽度,可以看示例代码
  • justificationWidth:缩放指定宽度

示例:

在这里插入图片描述

4)CTLineDraw

func CTLineDraw(_ line: CTLine,_ context: CGContext
)

绘制行。

5)CTLineGetGlyphCount

func CTLineGetGlyphCount(_ line: CTLine) -> CFIndex

获取行内字形总数。

6)CTLineGetGlyphRuns

func CTLineGetGlyphRuns(_ line: CTLine) -> CFArray

获取行内所有的CTRun。

7)CTLineGetStringRange

func CTLineGetStringRange(_ line: CTLine) -> CFRange

获取该行对应的字符范围。

8)CTLineGetPenOffsetForFlush

func CTLineGetPenOffsetForFlush(_ line: CTLine,_ flushFactor: CGFloat,_ flushWidth: Double
) -> Double

获取在指定宽度绘制时的水平偏移,一般配合 CGContext.textPosition 使用,可用于实现在固定宽度下文本的左对齐、右对齐、居中对齐及自定义水平偏移等。

示例:

在这里插入图片描述

9)CTLineGetImageBounds

func CTLineGetImageBounds(_ line: CTLine,_ context: CGContext?
) -> CGRect

获取行的​视觉边界​;注意 CTLineGetImageBounds 获取的是​相对于CTLine局部坐标系的矩形​,即以textPosition为原点的矩形。

视觉边界可以看下面的例子,与之相对的是布局边界;这个API在实际应用中不常见,除非有特殊诉求,比如要检测精确的内容点击范围,给行绘制紧贴背景等。

在这里插入图片描述

10)CTLineGetTypographicBounds

func CTLineGetTypographicBounds(_ line: CTLine,_ ascent: UnsafeMutablePointer<CGFloat>?,_ descent: UnsafeMutablePointer<CGFloat>?,_ leading: UnsafeMutablePointer<CGFloat>?
) -> Double

获取上行(ascent)、下行(descent)、行距(leading)。

这几个概念不熟悉的可以参考:一文读懂字符、字形、字体

想了解这几个数值最终是从哪个地方读取的可以参考:一文读懂字体文件

通过这个API我们可以手动构造​布局边界​(见上面的例子),一般用于点击检测、绘制行背景等。

11)CTLineGetTrailingWhitespaceWidth

func CTLineGetTrailingWhitespaceWidth(_ line: CTLine) -> Double

获取行尾空白字符的宽度(比如空格、制表符 (\t) 等),一般用于实现对齐时基于可见文本对齐等。

示例:

let line = CTLineCreateWithAttributedString(NSAttributedString(string: "Hello  ", attributes: [.font: UIFont.systemFont(ofSize: 16)])
)let totalWidth = CTLineGetTypographicBounds(line, nil, nil, nil)
let trailingWidth = CTLineGetTrailingWhitespaceWidth(line)print("总宽度: \(totalWidth)")
print("尾部空白宽度: \(trailingWidth)")
print("可见文字宽度: \(totalWidth - trailingWidth)")

12)CTLineGetStringIndexForPosition

func CTLineGetStringIndexForPosition(_ line: CTLine,_ position: CGPoint
) -> CFIndex

获取给定位置处的字符串索引。

​注意:​虽然官方文档说这个API一般用于点击检测,但实际测试下来​这个API返回的点击索引不准确​,比如虽然点击的是当前字符,但实际返回的索引是后一个字符的,如下:

在这里插入图片描述

查了下,发现这个API一般是用于计算光标位置的,比如点击「行」的左半部分,希望光标出现在「行」左侧,如果点击「行」的右半部分,希望光标出现在「行」的右侧。

如果我们想精确做字符的点击检测,推荐使用字符/行的bounds来计算,参考「CTFrame使用示例-3」例子。

13)CTLineGetOffsetForStringIndex

func CTLineGetOffsetForStringIndex(_ line: CTLine,_ charIndex: CFIndex,_ secondaryOffset: UnsafeMutablePointer<CGFloat>?
) -> CGFloat

获取指定字符索引相对于行的 x 轴偏移量。

  • line:待查询的行
  • charIndex:要查询的字符在原始属性字符串中的索引
  • secondaryOffset:次要偏移值,在简单的LTR文本中,可以忽略(传nil即可),但在复杂的双向文本(BiDi)中会用到

使用场景:

  • 字符点击检测:见「CTFrame使用示例-3」例子
  • 给某段字符绘制高亮和下划线
  • 定位某个字符:比如想在一段文本中的某个字符上方显示弹窗,可以用这个API先定位该字符

14)CTLineEnumerateCaretOffsets

func CTLineEnumerateCaretOffsets(_ line: CTLine,_ block: @escaping (Double, CFIndex, Bool, UnsafeMutablePointer<Bool>) -> Void
)

遍历一行中光标所有的有效位置。

  • line
  • block
    • Double:offset,相对于行的 x 轴偏移
    • CFIndex:与此光标位置相关的字符串索引
    • Bool:true 表示光标位于字符的前边(在 LTR 中即左侧),false 表示光标位于字符的后边(在 LTR 中即右侧);在 BiDi 中需要特殊同一个字符可能会回调两次(比如 BiDi 边界的地方),需要用这个值区分前后
    • UnsafeMutablePointer:stop 指针,赋值为 true 会停止遍历

使用场景:

  • 绘制光标:富文本选区或者文本编辑器中,要绘制光标时,可以先通过 CTLineGetStringIndexForPosition 获取字符索引,再通过这个函数或者 CTLineGetOffsetForStringIndex 获取光标偏移
  • 实现光标的左右键移动:可以用这个API将所有的光标位置存储到数组,并按offset排序,当用户按下右箭头 -> 时,可以找到当前光标index,将index + 1即是下一个光标位置

3.3.1 CTLine使用示例

除了上面例子,再举一个:

1)高亮特定字符

在这里插入图片描述

3.4 CTRun

CTRun相关API比较基础,这里主要介绍常用的。

1)CTLineGetGlyphRuns

func CTLineGetGlyphRuns(_ line: CTLine) -> CFArray

获取CTRun的唯一方式。

2)CTRunGetAttributes

func CTRunGetAttributes(_ run: CTRun) -> CFDictionary

获取CTRun的属性;比如想知道这个CTRun是不是粗体,是不是链接,是不是目标Run等,都可以通过这个API。

示例:

guard let attributes = CTRunGetAttributes(run) as? [NSAttributedString.Key: Any] else { continue }
// 现在你可以检查属性
if let color = attributes[.foregroundColor] as? UIColor {// ...
}
if let font = attributes[.font] as? UIFont {// ...
}
if let link = attributes[NSAttributedString.Key("my_custom_link_key")] {// 这就是那个可点击的 run!
}

3)CTRunGetStringRange

func CTRunGetStringRange(_ run: CTRun) -> CFRange

获取CTRun对应于原始属性字符串的哪个范围。

4)CTRunGetTypographicBounds

func CTRunGetTypographicBounds(_ run: CTRun,_ range: CFRange,_ ascent: UnsafeMutablePointer<CGFloat>?,_ descent: UnsafeMutablePointer<CGFloat>?,_ leading: UnsafeMutablePointer<CGFloat>?
) -> Double

获取CTRun的度量信息,同上面许多API一样,当 range.length 为0时表示直到CTRun文本末尾。

5)CTRunGetPositions

func CTRunGetPositions(_ run: CTRun,_ range: CFRange,_ buffer: UnsafeMutablePointer<CGPoint>
)

获取CTRun中每一个字形的位置,注意这里的位置是相对于CTLine原点的。

6)CTRunDelegate

CTRunDelegate允许为属性字符串中的一段文本提供自定义布局测量信息,一般用于在文本中插入图片、自定义View等非文本元素。

比如在文本中间插入图片:

在这里插入图片描述

3.4.1 CTRun使用示例

1)基础绘制

在这里插入图片描述

2)链接点击识别

在这里插入图片描述

3.5 CTTypesetter

CTFramesetter会自动处理换行,当我们想手动控制换行时,可以用CTTypesetter。

1)CTTypesetterSuggestLineBreak

func CTTypesetterSuggestLineBreak(_ typesetter: CTTypesetter,_ startIndex: CFIndex,_ width: Double
) -> CFIndex

按单词(word)换行。

如下示例,输出:Try word wrapping

let attrStringWith = NSAttributedString(string: "Try word wrapping", attributes: [.font: UIFont.systemFont(ofSize: 18)])
let typesetter = CTTypesetterCreateWithAttributedString(attributedString)
let totalLength = attributedString.length // UTF-16 长度
var startIndex = 0
var lineCount = 1while startIndex < totalLength {let charCount = CTTypesetterSuggestLineBreak(typesetter, startIndex, 100)// 如果返回 0,意味着一个字符都放不下(或已结束)if charCount == 0 {if startIndex < totalLength {print("Line \(lineCount): (Error) 无法放下剩余字符。")}break}// 获取这一行的子字符串let range = NSRange(location: startIndex, length: charCount)let lineString = (attributedString.string as NSString).substring(with: range)print("Line \(lineCount): '\(lineString)' (UTF-16 字符数: \(charCount))")// 更新下一次循环的起始索引startIndex += charCountlineCount += 1
}

2)CTTypesetterSuggestClusterBreak

func CTTypesetterSuggestClusterBreak(_ typesetter: CTTypesetter,_ startIndex: CFIndex,_ width: Double
) -> CFIndex

按字符(char)换行。

如下示例,输出:Try word wrapping

let attrStringWith = NSAttributedString(string: "Try word wrapping", attributes: [.font: UIFont.systemFont(ofSize: 18)])
let typesetter = CTTypesetterCreateWithAttributedString(attributedString)
let totalLength = attributedString.length // UTF-16 长度
var startIndex = 0
var lineCount = 1while startIndex < totalLength {let charCount = CTTypesetterSuggestClusterBreak(typesetter, startIndex, 100)// 如果返回 0,意味着一个字符都放不下(或已结束)if charCount == 0 {if startIndex < totalLength {print("Line \(lineCount): (Error) 无法放下剩余字符。")}break}// 获取这一行的子字符串let range = NSRange(location: startIndex, length: charCount)let lineString = (attributedString.string as NSString).substring(with: range)print("Line \(lineCount): '\(lineString)' (UTF-16 字符数: \(charCount))")// 更新下一次循环的起始索引startIndex += charCountlineCount += 1
}

四、总结

以上是CoreText中常用的API及其场景代码举例,完整示例代码可在公众号「非专业程序员Ping」回复 “CoreText” 获取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/940639.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

存算一体架构的先行者:RustFS在异构计算环境下的探索与实践

存算一体架构的先行者:RustFS在异构计算环境下的探索与实践随着AI大模型与边缘计算蓬勃发展,传统"存储-计算"分离架构的"存储墙"瓶颈日益凸显。本文将深入解析RustFS如何通过存算一体设计在异构…

Appium 3.0:跨平台移动自动化测试框架全面解析

Appium是一个开源的跨平台自动化测试框架,支持原生、混合、移动Web和桌面应用的测试。基于WebDriver协议,提供丰富的驱动和插件生态系统,支持多种编程语言,让移动应用测试变得更加简单高效。Appium 3.0:跨平台移动…

德国州政府全面弃用微软办公套件,改用开源方案

德国州政府全面弃用微软办公套件,改用开源方案德国州政府全面弃用微软办公套件,改用开源方案来源: OSCHINA 编辑: 局 2025-10-16 19:24:043德国石勒苏益格 - 荷尔斯泰因州宣布,已正式完成从微软 Outlook 和 Exchang…

DAPO代码实现浅析

参考verl对dapo的实现,首先咱们看一下入口.sh和.py文件,在./recipe/dapo/文件夹中有以下目录 . ├── config │ ├── dapo_megatron_trainer.yaml │ └── dapo_trainer.yaml ├── dapo_ray_trainer.py …

[KaibaMath]1011 关于收敛数列保号性的证明

[KaibaMath]1011 关于收敛数列保号性的证明收敛数列保号性是描述收敛数列的极限符号与数列“后期项”符号关系的核心性质,即极限的非零符号能“保证”数列从某一项开始的所有项与极限同号。下面给出证明。

赛前训练 12 extra 树上差分倍增

A 树上差分板子. B 每个点只有一条出边的有向图可以看作树 基于上述结论,我们直接倍增维护 \(\min,\operatorname{sum}\) 即可.实现 #include <cstdio> #include <iostream> #include <algorithm> #…

塔吊施工人员操作合规性监测!思通数科 AI 卫士实时守护作业安全

塔吊施工中,人员操作合规性是安全管理的关键环节,但传统人工监管常面临 “监管范围有限、异常难实时发现” 的痛点:作业人员是否按规范穿戴防护装备(安全帽、防护服、防护手套),靠远处观察难判断穿戴完整性(如安…

Dos命令1

常用的dos命令 我不懂

题解:P1073 [NOIP 2009 提高组] 最优贸易

题目传送门 绝世好题 让我学会了分层图的真正用法 以前都只会自作聪明地分两层: 美其名曰【正图】【反图】 现在知道了还有这种神奇的建图方法!理解题意: 有向图 给定起点终点 求路径上两点买卖东西最大收益 思路:…

吩咐

吩咐rt。不知道要写些什么。 Q/A 或者别的。 记忆力可能比较差,可能会有内容错乱。Q以下是博客签名,正文无关 本文来自博客园,作者:Wy_x,转载请在文首注明原文链接:https://www.cnblogs.com/Wy-x/p/19151449 版权…

互评五

一、数据存储结构不同 ArrayImpl: 使用固定大小的数组 Student[] students ListImpl: 使用动态数组 ArrayList students 构造函数差异 ArrayImpl: 需要指定初始大小 public StudentDaoArrayImpl(int size) ListImpl: 无…

ACS ACR122 0 是啥

ACS ACR122 0 是啥你提到的 “ACS ACR122 0”,实际上指的是一个 NFC 读卡器(RFID Reader)。 下面我详细给你讲清楚它是什么、怎么用、以及它为什么会在系统里显示成那个名字。🪪 一、设备全称 ACS ACR122U NFC Re…

C++ std::forwardT 的使用

C++ std::forwardC++ std::forward 的使用 C++真实一门细节比较多的语言,稍不注意就会出现奇怪请琢磨不透的bug,这时候就说明你的C++基础不扎实。 C++ lvalue rvalue std::string hello = "Hello World";顾…

机器人技术新前沿:自动驾驶路径规划算法解析

本文深入探讨了自动驾驶机器人出租车技术的核心算法,包括基于机器学习的路径规划、环境感知与行为预测系统,并对比了火星探测器与城市自动驾驶在技术挑战上的差异。机器人技术新前沿 某中心子公司Zoox首席软件工程师…

前端框架文档新思路:基于源码解析的自动化方案

项目背景 最近我们团队自研了一个基于 React 的 H5 前端框架,领导让我来负责编写框架的使用文档。我选择了 dumi 来搭建文档站点,大部分内容都是手动写 Markdown 来介绍各种功能,包括:初始化、目录结构、生命周期、…

tryhackme-预安全-网络基础知识-数据包和帧-07

tryhackme-Pre Security-Pre Security-Network Fundamentals-Packets & Frames 房间地址:https://tryhackme.com/room/packetsframes 这是网络安全入门的基础模块的计算机科学基础知识:Packets & Frames(数…

Agilent E363x 系列

Agilent E363x 系列⚙️ 一、Agilent E363x 是什么设备 Agilent E363x(也写作 E3630 / E3631 / E3632 / E3633 / E3634 等型号) 是一系列由 Agilent Technologies(现 Keysight Technologies) 出品的 👉 可编程直流…

嗣澳——扫,墨依奥——描,希伊桉——线

rt: 扫描线 定义 扫描线顾名思义就是用线扫描,维护区间的长度。它一般被用来解决图形面积,周长问题。 rt:把整个矩形分成如图各个颜色不同的小矩形,小矩形的高是扫过的距离,然而矩形的水平宽一直在变化。 给每一个…

迈向零信任存储:基于RustFS构建内生安全的数据架构

迈向零信任存储:基于RustFS构建内生安全的数据架构在数据泄露事件频发的当下,传统边界安全模型已不足以保护企业核心数据资产。本文将深入解析如何基于RustFS构建​内生安全的零信任存储架构,实现从“信任网络”到“…