mcpField
T
text-editing

text-editing

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

关于 text-editing

面向 SwiftUI 开发者的文本显示与富文本编辑指南,涵盖 Text、AttributedString、选区格式化及 Markdown 支持范围。

主要功能

  1. 01SwiftUI 文本样式
  2. 02AttributedString 格式化
  3. 03基于选区的富文本编辑
  4. 04自定义格式约束
  5. 05行内 Markdown 指引

适用场景

  1. 01在 SwiftUI 视图中设置只读文本样式
  2. 02为文本编辑器添加格式控件
  3. 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最低版本备注
带修饰符的 TextiOS 13.font()、.bold()、.italic()
TextEditor(text:)iOS 14纯字符串绑定
.foregroundStyle()iOS 15优先于 .foregroundColor()
AttributedStringiOS 15富文本模型
.bold(condition)iOS 16条件式粗体/斜体
.underline(pattern:)iOS 16虚线、点线样式
TextEditor(text:selection:)iOS 18AttributedString + 选区
AttributedTextSelectioniOS 18基于选区的格式设置
text.transformAttributes(in:)iOS 18修改选区中的属性
AttributedTextFormattingDefinitioniOS 18自定义格式限制
@Environment(\.fontResolutionContext)iOS 18解析字体属性

最常见的 5 个错误

#错误修正方法
1在新项目中使用 .foregroundColor()使用 .foregroundStyle()——支持渐变和 ShapeStyle
2在文本上使用不带 value: 的 .animation(.spring())已在 iOS 15 中弃用——始终传入 value: 参数
3期待 Text 完全支持 MarkdownText 只支持行内 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)
可用属性
属性类型示例
.fontFont.headline
.foregroundColorColor.red
.backgroundColorColor.yellow
.underlineStyleUnderlineStyle.single
.underlineColorColor.blue
.strikethroughStyleUnderlineStyle.single
.strikethroughColorColor.red
.inlinePresentationIntentInlinePresentationIntent.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