mcpField
A
attributed-string

attributed-string

github.com/rshankras设计与 UI83877 次安装14 周前更新
代码仓库

关于 attributed-string

面向 Swift 开发者的 Foundation AttributedString 使用指南,涵盖文本样式、段落格式、选区编辑和 SwiftUI 集成。内容说明新旧 API 的用法及系统版本要求。

主要功能

  1. 01设置文本字体、颜色和下划线
  2. 02控制对齐、方向与行高
  3. 03替换和编辑文本选区
  4. 04处理不连续文本范围
  5. 05在 SwiftUI 中显示和编辑富文本

适用场景

  1. 01为文本片段应用样式
  2. 02调整段落对齐和行距
  3. 03在编辑器中替换所选文字
  4. 04构建 SwiftUI 富文本编辑界面

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rshankras/claude-code-apple-skills --skill attributed-string

安装后在 Claude Code 中输入/attributed-string确认已加载。

详细介绍

AttributedString 模式

Foundation AttributedString 的正确 API 结构和模式。涵盖创建样式文本、为范围应用属性、文本对齐、书写方向、行高控制、文本选择与编辑、不连续子字符串,以及 SwiftUI 集成。

此技能的触发时机

在用户遇到以下情况时使用此技能:

  • 询问如何创建或操作 AttributedString
  • 想要使用字体、颜色、下划线或其他属性来设置文本样式
  • 提到文本对齐、书写方向或行高
  • 询问如何使用 AttributedString 选择文本或编辑文本
  • 想要使用 DiscontiguousAttributedSubstring 或 RangeSet
  • 在 SwiftUI 中提到 TextEditor 与 AttributedString
  • 询问 Swift 中的富文本格式
  • 想要替换或修改 AttributedString 中的文本
  • 提到 paragraphStyle、textSelectionAffinity 或 AttributedTextSelection

决策树

What do you need with AttributedString?
|
+-- Create or style text
|   |
|   +-- Simple inline attributes (font, color)
|   |   --> Creating and Styling section
|   |
|   +-- Paragraph-level formatting (alignment, line height)
|       --> Text Alignment and Formatting section
|
+-- Control text layout
|   |
|   +-- Writing direction (LTR / RTL)
|   |   --> Writing Direction and Line Height section
|   |
|   +-- Line spacing / height
|       --> Writing Direction and Line Height section
|
+-- Edit or select text programmatically
|   |
|   +-- Replace selection with characters or AttributedString
|   |   --> Text Selection and Editing section
|   |
|   +-- Work with multiple non-contiguous ranges
|       --> DiscontiguousAttributedSubstring section
|
+-- Display in SwiftUI
    --> SwiftUI Integration section

API 可用性

API最低版本说明
AttributedStringiOS 15 / macOS 12NSAttributedString 的 Swift 原生替代方案
AttributedString.paragraphStyleiOS 15 / macOS 12使用 NSMutableParagraphStyle
AttributedString.writingDirectioniOS 26 / macOS 262025 年新增
AttributedString.LineHeightiOS 26 / macOS 26.exact(points:)、.multiple(factor:)、.loose
AttributedString.alignmentiOS 26 / macOS 26.left、.center、.right
AttributedTextSelectioniOS 26 / macOS 26以编程方式选择文本
replaceSelection(_:withCharacters:)iOS 26 / macOS 26将所选内容替换为纯文本字符
replaceSelection(_:with:)iOS 26 / macOS 26将所选内容替换为 AttributedString
DiscontiguousAttributedSubstringiOS 26 / macOS 26非连续范围选择
AttributedString.utf8iOS 26 / macOS 26UTF-8 代码单元视图
使用 AttributedString 的 TextEditor(text:selection:)iOS 26 / macOS 26SwiftUI 富文本编辑
.textSelectionAffinity(_:)iOS 26 / macOS 26控制行边界处的光标亲和性

最常见的 5 个错误

#错误修正方法
1在新的 Swift 代码中使用 NSAttributedString使用 AttributedString(iOS 15+),获得类型安全的 Swift 原生属性
2未检查范围是否存在就应用基于范围的属性对 text.range(of:) 的结果始终进行安全解包,再用下标访问
3忘记 AttributedString 是值类型修改需要使用 var,而非 let;声明为 var 后再赋值属性
4新的对齐 API 已可用,却仍在创建 NSMutableParagraphStyle在 iOS 26+ 上使用 text.alignment = .center,而非手动设置段落样式
5使用 replaceSelection 时修改原字符串,而非所选内容将选择作为 inout 传入,让 API 为你更新选择范围

创建和设置样式

基本初始化
// Plain text
let plain = AttributedString("Hello, world!")

// With attributes applied inline
var bold = AttributedString("Bold text")
bold.font = .boldSystemFont(ofSize: 16)
为范围应用属性
var text = AttributedString("Styled text")
text.foregroundColor = .red
text.backgroundColor = .yellow
text.font = .systemFont(ofSize: 14)

// Attribute on a specific range
if let range = text.range(of: "Styled") {
    text[range].underlineStyle = .single
    text[range].underlineColor = .blue
}
从子字符串创建
let source = AttributedString("Hello, world!")
if let range = source.range(of: "world") {
    let substring = source[range]
    let extracted = AttributedString(substring) // standalone copy
}
模式结论
var text = AttributedString("..."),然后修改正确
let text = AttributedString("..."),然后修改无法编译——值类型需要使用 var
对 text.range(of:)! 强制解包不可靠——请使用 if let 或 guard let

文本对齐和格式设置

旧版方法(iOS 15+)
var paragraph = AttributedString("Centered paragraph of text")
let style = NSMutableParagraphStyle()
style.alignment = .center
paragraph.paragraphStyle = style
新版方法(iOS 26+)
var paragraph = AttributedString("Centered paragraph of text")
paragraph.alignment = .center

可用的 TextAlignment 值:

值说明
.left左对齐文本
.right右对齐文本
.center居中对齐文本

书写方向和行高

书写方向(iOS 26+)
var text = AttributedString("Hello عربي")
text.writingDirection = .rightToLeft
值说明
.leftToRight标准的从左到右布局
.rightToLeft适用于阿拉伯语、希伯来语等语言的从右到左布局
行高(iOS 26+)
var multiline = AttributedString(
    "This is a paragraph\nwith multiple lines\nof text."
)

// Exact point value
multiline.lineHeight = .exact(points: 32)

// Multiplier of the default line height
multiline.lineHeight = .multiple(factor: 2.5)

// System-defined loose spacing
multiline.lineHeight = .loose
模式用例
.exact(points:)需要固定行高的像素级精准设计
.multiple(factor:)相对于字体大小按比例缩放
.loose由系统选择舒适的阅读间距

文本选择与编辑

替换选中文本(iOS 26+)
var text = AttributedString("Here is my dog")
var selection = AttributedTextSelection(range: text.range(of: "dog")!)

// Replace with plain characters
text.replaceSelection(&selection, withCharacters: "cat")

// Replace with an AttributedString
let replacement = AttributedString("horse")
text.replaceSelection(&selection, with: replacement)

要点:纯文本使用 withCharacters:,带样式的替换内容使用 with:。

不连续的 AttributedString 子串

同时选择和操作多个不连续的范围(iOS 26+)。

let text = AttributedString("Select multiple parts of this text")

if let range1 = text.range(of: "Select"),
   let range2 = text.range(of: "text") {
    let rangeSet = RangeSet([range1, range2])
    var substring = text[rangeSet] // DiscontiguousAttributedSubstring
    substring.backgroundColor = .yellow

    // Flatten into a single contiguous AttributedString
    let combined = AttributedString(substring)
}

UTF-8 视图

访问原始 UTF-8 代码单元(iOS 26+):

let text = AttributedString("Hello")
for codeUnit in text.utf8 {
    print(codeUnit)
}

SwiftUI 集成

使用 AttributedString 和 Selection 的 TextEditor(iOS 26+)
struct SuggestionTextEditor: View {
    @State var text: AttributedString = ""
    @State var selection = AttributedTextSelection()

    var body: some View {
        VStack {
            TextEditor(text: $text, selection: $selection)
            SuggestionsView(
                substrings: getSubstrings(
                    text: text,
                    indices: selection.indices(in: text)
                )
            )
        }
    }
}
文本选择亲和性

控制光标位于行边界时显示在哪一行:

TextEditor(text: $text, selection: $selection)
    .textSelectionAffinity(.upstream)

.upstream 会将光标保留在上一行的末尾;.downstream 会将光标移至下一行的开头。

在 SwiftUI 中显示带样式的文本
// Simple display
Text(attributedString)

// With text selection enabled
Text(attributedString)
    .textSelection(.enabled)

审核清单

正确性
  • 新的 Swift 代码使用 AttributedString(而非 NSAttributedString)
  • 使用 if let 或 guard let 安全解包所有范围查找结果
  • 应用属性前,将字符串声明为 var
  • replaceSelection 通过 inout(&selection)传递 selection
平台与版本
  • 新 API(alignment、writingDirection、lineHeight、selection)限定在 iOS 26+ / macOS 26+
  • 面向 iOS 15-25 的目标使用旧版段落样式方案
  • 支持较旧的部署目标时,使用可用性检查(if #available)包裹较新的 API
SwiftUI
  • 富文本编辑使用 TextEditor(text:selection:) 重载(iOS 26+)
  • 在换行处的光标行为很重要时,应用 .textSelectionAffinity
  • 在显示用户内容的 Text 视图上添加 .textSelection(.enabled)
无障碍
  • 前景色与背景色组合符合对比度要求
  • 带样式的文本不只依靠颜色传达含义(添加下划线、粗体或图标)
  • 为 RTL 语言内容正确设置书写方向

参考资料

评论

支持 Markdown