了解如何使用 swiftui 的 texteditor api 和 attributedstring 构建富文本体验。探索如何启用富文本编辑功能、构建用来操控编辑器内容的自定控件,并对提供的众多格式选项进行自定。了解 attributedstring 的高级功能,以便精心打造超棒的文本编辑体验。

视频封面
视频地址

此文章由AI生成,可能存在错误,如有问题,请联系djs66256@163.com

使用 SwiftUI 和 AttributedString 构建精美富文本编辑器

在 WWDC 的技术演讲中,SwiftUI 团队的 Max 和 Swift 标准库团队的 Jeremy 共同介绍了如何利用 SwiftUI 的 TextEditor API 和 AttributedString 创建功能丰富的富文本编辑器。以下是本次演讲的技术要点解析。

从纯文本到富文本编辑器

基础 TextEditor 实现

纯文本编辑器可以通过 SwiftUI 的 TextEditor API 轻松实现:

import SwiftUI

struct RecipeEditor: View {
    @Binding var text: String

    var body: some View {
        TextEditor(text: $text)
    }
}

这种实现仅支持基本的字符串编辑功能,适用于简单的文本输入场景。

升级为富文本支持

将 String 替换为 AttributedString 即可实现富文本支持:

import SwiftUI

struct RecipeEditor: View {
    @Binding var text: AttributedString

    var body: some View {
        TextEditor(text: $text)
    }
}

升级后的编辑器支持以下丰富的文本格式功能:

  • 基本样式:加粗、斜体、下划线、删除线
  • 字体调整:自定义字体、字号
  • 颜色设置:前景色、背景色
  • 排版细节:字距调整、基线偏移
  • 特殊内容:Genmoji
  • 段落样式:行高、对齐方式、书写方向

特别值得注意的是,这些属性与 SwiftUI 的非可编辑 Text 视图完全兼容,可以实现无缝的内容展示转换。

编辑器功能扩展

选区处理与自定义控件

在实际应用中,开发者常需要处理文本选区并添加自定义功能。演讲中展示了如何实现通过选中文本一键添加配料的功能:

import SwiftUI

struct RecipeEditor: View {
    @Binding var text: AttributedString
    @State private var selection = AttributedTextSelection()

    var body: some View {
        TextEditor(text: $text, selection: $selection)
            .preference(key: NewIngredientPreferenceKey.self, value: newIngredientSuggestion)
    }

    private var newIngredientSuggestion: IngredientSuggestion {
        let name = text[selection]

        return IngredientSuggestion(
            suggestedName: AttributedString(name))
    }
}

关键技术点:

  • 使用 AttributedTextSelection 处理文本选区
  • 通过选区下标直接获取选定内容
  • 结合 PreferenceKey 实现自定义功能

文本格式的精细控制

演讲还介绍了如何通过 AttributedTextFormattingDefinition 协议定制编辑器支持的属性范围:

struct RecipeFormattingDefinition: AttributedTextFormattingDefinition {
    struct Scope: AttributeScope {
        let foregroundColor: AttributeScopes.SwiftUIAttributes.ForegroundColorAttribute
        let adaptiveImageGlyph: AttributeScopes.SwiftUIAttributes.AdaptiveImageGlyphAttribute
        let ingredient: IngredientAttribute
    }

    var body: some AttributedTextFormattingDefinition<Scope> {
        // 具体实现
    }
}

开发者可以添加约束条件来确保特定的格式规则,例如强制配料名称显示为绿色:

struct IngredientsAreGreen: AttributedTextValueConstraint {
    typealias Scope = RecipeFormattingDefinition.Scope
    typealias AttributeKey = AttributeScopes.SwiftUIAttributes.ForegroundColorAttribute

    func constrain(_ container: inout Attributes) {
        if container.ingredient != nil {
            container.foregroundColor = .green
        } else {
            container.foregroundColor = nil
        }
    }
}

高级属性控制

通过 AttributedStringKey 协议可以对属性行为进行精细控制:

struct IngredientAttribute: CodableAttributedStringKey {
    typealias Value = Ingredient.ID

    static let name = "SampleRecipeEditor.IngredientAttribute"

    static let inheritedByAddedText: Bool = false // 新增文本不继承属性
    static let invalidationConditions: Set<AttributedString.AttributeInvalidationCondition>? = [.textChanged] // 文本变化时失效
}

这些控制选项让开发者能够:

  • 决定属性是否会被新增文本继承
  • 设置属性失效条件
  • 实现更复杂的文本交互行为

总结与资源

SwiftUI 的 TextEditor 配合 AttributedString 提供了强大的富文本编辑能力,开发者可以在此基础上:

  • 构建自定义控件增强编辑体验
  • 实施精细的格式控制规则
  • 创建独特的文本交互模式

AttributedString 作为 Swift 开源项目的一部分,欢迎开发者通过 GitHub 参与贡献或在 Swift 论坛交流经验。

相关视频

提升 App 的多语言体验
向左语言
Foundation 中的新功能

文档参考

AttributedTextFormatting
AttributedTextSelection
Character