关于 text-editing
面向 SwiftUI 开发者的文本显示与富文本编辑指南,涵盖 Text、AttributedString、选区格式化及 Markdown 支持范围。
主要功能
- 01SwiftUI 文本样式
- 02AttributedString 格式化
- 03基于选区的富文本编辑
- 04自定义格式约束
- 05行内 Markdown 指引
适用场景
- 01在 SwiftUI 视图中设置只读文本样式
- 02为文本编辑器添加格式控件
- 03使用 iOS 18 API 格式化选中文本
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ rshankras/ claude-code-apple-skills --skill text-editing安装后在 Claude Code 中输入/text-editing确认已加载。
详细介绍
样式文本编辑
介绍在 SwiftUI 中显示样式文本和构建富文本编辑器的模式。涵盖 Text 样式、AttributedString、使用基于选区的格式设置的 TextEditor,以及自定义格式定义。
此技能的适用场景
在以下情况下使用此技能:
- 想要显示样式化或格式化的文本
- 需要带有粗体/斜体/下划线控件的富文本编辑
- 询问 AttributedString 或 TextEditor
- 想要文本格式工具栏
- 询问 Text 视图中的 Markdown 渲染
- 需要自定义文本属性或格式限制
- 想要基于选区设置文本格式
决策树
What text feature do you need?
|
+- Display styled read-only text
| +- Simple styling (one style) -> Text Styling section below
| +- Mixed styles in one string -> AttributedString section below
| +- Markdown content -> Markdown section below
|
+- Edit plain text
| +- TextEditor(text: $stringBinding)
|
+- Edit rich/styled text
| +- Basic rich editor -> Rich Text Editing section below
| +- With formatting toolbar -> Formatting Controls section below
| +- With custom constraints -> Custom Formatting section below
API 可用性
| API | 最低版本 | 备注 |
|---|---|---|
带修饰符的 Text | iOS 13 | .font()、.bold()、.italic() |
TextEditor(text:) | iOS 14 | 纯字符串绑定 |
.foregroundStyle() | iOS 15 | 优先于 .foregroundColor() |
AttributedString | iOS 15 | 富文本模型 |
.bold(condition) | iOS 16 | 条件式粗体/斜体 |
.underline(pattern:) | iOS 16 | 虚线、点线样式 |
TextEditor(text:selection:) | iOS 18 | AttributedString + 选区 |
AttributedTextSelection | iOS 18 | 基于选区的格式设置 |
text.transformAttributes(in:) | iOS 18 | 修改选区中的属性 |
AttributedTextFormattingDefinition | iOS 18 | 自定义格式限制 |
@Environment(\.fontResolutionContext) | iOS 18 | 解析字体属性 |
最常见的 5 个错误
| # | 错误 | 修正方法 |
|---|---|---|
| 1 | 在新项目中使用 .foregroundColor() | 使用 .foregroundStyle()——支持渐变和 ShapeStyle |
| 2 | 在文本上使用不带 value: 的 .animation(.spring()) | 已在 iOS 15 中弃用——始终传入 value: 参数 |
| 3 | 期待 Text 完全支持 Markdown | Text 只支持行内 Markdown:粗体、斜体、[链接]。不支持列表、表格、代码块、图片 |
| 4 | 每次计算 body 时都创建新的 AttributedString 实例 | 将复杂的 AttributedString 对象缓存到 @State 中,或定义为 body 外的计算属性 |
| 5 | 使用 TextEditor(text: $string) 实现富文本 | 使用 TextEditor(text: $attributedString, selection: $selection) 并绑定 AttributedString(iOS 18+) |
Text 样式速查
// Font
Text("Hello").font(.headline)
Text("Custom").font(.system(size: 24, design: .rounded))
// Weight
Text("Bold").fontWeight(.bold)
// Color — prefer foregroundStyle over foregroundColor
Text("Styled").foregroundStyle(.red)
Text("Gradient").foregroundStyle(
.linearGradient(colors: [.yellow, .blue], startPoint: .top, endPoint: .bottom)
)
// Decorations
Text("Bold").bold()
Text("Conditional").bold(someCondition)
Text("Underline").underline(true, pattern: .dash, color: .blue)
Text("Strike").strikethrough(true, pattern: .dot, color: .red)
// Layout
Text("Centered").multilineTextAlignment(.center)
Text("Spaced").lineSpacing(10)
Text("Truncated").lineLimit(2).truncationMode(.tail)
AttributedString
// Create and style ranges
var text = AttributedString("Red and Blue")
if let redRange = text.range(of: "Red") {
text[redRange].foregroundColor = .red
text[redRange].font = .headline
}
if let blueRange = text.range(of: "Blue") {
text[blueRange].foregroundColor = .blue
text[blueRange].underlineStyle = .single
}
// Display
Text(text)
可用属性
| 属性 | 类型 | 示例 |
|---|---|---|
.font | Font | .headline |
.foregroundColor | Color | .red |
.backgroundColor | Color | .yellow |
.underlineStyle | UnderlineStyle | .single |
.underlineColor | Color | .blue |
.strikethroughStyle | UnderlineStyle | .single |
.strikethroughColor | Color | .red |
.inlinePresentationIntent | InlinePresentationIntent | .stronglyEmphasized(粗体)、.emphasized(斜体) |
富文本编辑(iOS 18+)
struct RichTextEditorView: View {
@State private var text = AttributedString("Select text to format")
@State private var selection = AttributedTextSelection()
@Environment(\.fontResolutionContext) private var fontResolutionContext
var body: some View {
VStack {
TextEditor(text: $text, selection: $selection)
.frame(height: 200)
HStack {
Button(action: toggleBold) {
Image(systemName: "bold")
}
Button(action: toggleItalic) {
Image(systemName: "italic")
}
Button(action: toggleUnderline) {
Image(systemName: "underline")
}
}
}
}
private func toggleBold() {
text.transformAttributes(in: &selection) {
let font = $0.font ?? .default
let resolved = font.resolve(in: fontResolutionContext)
$0.font = font.bold(!resolved.isBold)
}
}
private func toggleItalic() {
text.transformAttributes(in: &selection) {
let font = $0.font ?? .default
let resolved = font.resolve(in: fontResolutionContext)
$0.font = font.italic(!resolved.isItalic)
}
}
private func toggleUnderline() {
text.transformAttributes(in: &selection) {
if $0.underlineStyle != nil {
$0.underlineStyle = nil
} else {
$0.underlineStyle = .single
}
}
}
}
读取选区属性
// Get current attributes at the selection/cursor
let attributes = selection.typingAttributes(in: text)
let currentColor = attributes.foregroundColor ?? .primary
自定义格式定义(iOS 18+)
限制编辑器中可用的格式选项:
struct MyTextFormatting: AttributedTextFormattingDefinition {
typealias Scope = AttributeScopes.SwiftUIAttributes
static let fontWeight = ValueConstraint(
\.font,
constraint: { font in
guard let font = font else { return nil }
let weight = font.resolve().weight
return font.weight(weight == .bold ? .regular : .bold)
}
)
}
// Apply to TextEditor
TextEditor(text: $text, selection: $selection)
.textFormattingDefinition(MyTextFormatting.self)
Text 中的 Markdown
// Inline markdown support
Text("This is **bold** and *italic* text")
Text("Visit [Apple](https://www.apple.com)")
Text("Code: `inline code`")
Markdown 的限制
Text 只支持行内 Markdown:
- ✅ 粗体(
**text**)、斜体(*text*)、链接、行内代码 - ❌ 换行、块级格式、列表、表格、代码块、图片、块引用
审核清单
文本显示
- 使用
.foregroundStyle(),而非已弃用的.foregroundColor() -
.lineLimit()与.help()提示或.textSelection(.enabled)配合使用,处理截断文本 - 支持动态字体——使用系统字体样式,而非硬编码字号
- 颜色可适配深色模式——使用系统颜色或语义样式
AttributedString
- 在 @State 中缓存复杂的 AttributedString,而不是在 body 中重新创建
- 范围查找使用安全的
if let range = text.range(of:)模式 - 使用恰当的属性(语义粗体/斜体使用
.inlinePresentationIntent)
TextEditor
- 富文本使用
TextEditor(text: $attributedString, selection: $selection)(iOS 18+) - 格式工具栏使用
text.transformAttributes(in: &selection)模式 - 切换逻辑使用
@Environment(\.fontResolutionContext)解析字体 - 为格式按钮提供无障碍标签
本地化
- 面向用户的字符串使用
LocalizedStringKey - 本地化字符串中的 Markdown 使用
Text(LocalizedStringKey("**Bold** text"))
参考资料
评论
支持 Markdown