Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2025 App ServicesAI & Machine Learning

WWDC25 · 18 min · App Services / AI & Machine Learning

Dive deeper into Writing Tools

With Writing Tools, people can proofread, rewrite, and transform text directly within your app. Learn advanced techniques to customize Writing Tools for your app. Explore formatting options and how they work with rich text editing. If you have a custom text engine, learn how to seamlessly integrate the complete Writing Tools experience, allowing edits directly within the text view.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 8 snippets

Attach a coordinator to the view (UIKit) swift · at 11:46 ↗
// Attach a coordinator to the view
// UIKit

func configureWritingTools() {
    guard UIWritingToolsCoordinator.isWritingToolsAvailable else { return }

    let coordinator = UIWritingToolsCoordinator(delegate: self)
    addInteraction(coordinator)
}
Attach a coordinator to the view (AppKit) swift · at 12:02 ↗
// Attach a coordinator to the view
// AppKit

func configureWritingTools() {
    guard NSWritingToolsCoordinator.isWritingToolsAvailable else { return }
       
    let coordinator = NSWritingToolsCoordinator(delegate: self)

    coordinator.preferredBehavior = .complete
    coordinator.preferredResultOptions = [.richText, .list]
    writingToolsCoordinator = coordinator
}
Prepare the context swift · at 13:06 ↗
// Prepare the context

func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
        requestsContextsFor scope: NSWritingToolsCoordinator.ContextScope,
        completion: @escaping ([NSWritingToolsCoordinator.Context]) -> Void) {

    var contexts = [NSWritingToolsCoordinator.Context]()
                
    switch scope {
    case .userSelection:
        let context = getContextObjectForSelection()
        contexts.append(context)
        break
        // other cases…
    }
        
    // Save references to the contexts for later delegate calls.
    storeContexts(contexts)
    completion(contexts)
}
Respond to text changes from Writing Tools and update selected range swift · at 13:48 ↗
// Respond to text changes from Writing Tools

func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
        replace range: NSRange,
        in context: NSWritingToolsCoordinator.Context,
        proposedText replacementText: NSAttributedString,
        reason: NSWritingToolsCoordinator.TextReplacementReason,
        animationParameters: NSWritingToolsCoordinator.AnimationParameters?,
        completion: @escaping (NSAttributedString?) -> Void) {
}

// Update selected range

func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
        select ranges: [NSValue],
        in context: NSWritingToolsCoordinator.Context,
        completion: @escaping () -> Void) {
}
Generate preview for animation (AppKit) swift · at 14:41 ↗
// Generate preview for animation (macOS)

func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
        requestsPreviewFor textAnimation: NSWritingToolsCoordinator.TextAnimation,
        of range: NSRange,
        in context: NSWritingToolsCoordinator.Context,
        completion: @escaping ([NSTextPreview]?) -> Void) {
}
    
func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
        requestsPreviewFor rect: NSRect,
        in context: NSWritingToolsCoordinator.Context,
        completion: @escaping (NSTextPreview?) -> Void) {
}
Generate preview for animation (UIKit) swift · at 14:58 ↗
// Generate preview for animation (iOS)

func writingToolsCoordinator(_ writingToolsCoordinator: UIWritingToolsCoordinator,
        requestsPreviewFor textAnimation: UIWritingToolsCoordinator.TextAnimation,
        of range: NSRange,
        in context: UIWritingToolsCoordinator.Context,
        completion: @escaping (UITargetedPreview?) -> Void) {
}
Delegate callbacks before and after animation swift · at 15:08 ↗
// Generate preview for animation

func writingToolsCoordinator(
    _ writingToolsCoordinator: NSWritingToolsCoordinator,
    prepareFor textAnimation: NSWritingToolsCoordinator.TextAnimation,
    for range: NSRange,
    in context: NSWritingToolsCoordinator.Context,
    completion: @escaping () -> Void) {

    // Hide the specific range of text from the text view
}

func writingToolsCoordinator(
    _ writingToolsCoordinator: NSWritingToolsCoordinator,
    finish textAnimation: NSWritingToolsCoordinator.TextAnimation,
    for range: NSRange,
    in context: NSWritingToolsCoordinator.Context,
    completion: @escaping () -> Void) {

    // Show the specific range of text again
}
Delegate callbacks to show proofreading marks swift · at 15:39 ↗
// Create proofreading marks

func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
        requestsUnderlinePathsFor range: NSRange,
        in context: NSWritingToolsCoordinator.Context,
        completion: @escaping ([NSBezierPath]) -> Void) {
}

func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
        requestsBoundingBezierPathsFor range: NSRange,
        in context: NSWritingToolsCoordinator.Context,
        completion: @escaping ([NSBezierPath]) -> Void) {
}

Resources