1

Problem

I am working on a simple SwiftUI document-based app on macOS (12.0.1) with Xcode 13.2.1.

In my app, I need two TextEditors in the document view. One displays the content of the document, and the other is used to support some other functions.

What is troubling me is that when editing in either of these text editors, the document is set edited, as is in this screenshot. I wonder whether there is a way to prevent the second TextEditor from doing this.


Code

This is the DocumentView to display the document with 2 TextEditors. Only the first one is meant to show the document content.

struct DocumentView: View {
    @Binding var document: Document
    @State private var string = ""
    var body: some View {
        TextEditor(text: $document.text)
        TextEditor(text: $string)
    }
}

The code for the app and the document structure is the same as the Xcode template:

import SwiftUI

@main
struct SwiftUIApp: App {
    var body: some Scene {
        DocumentGroup(newDocument: CPDocument()) { a in
            DocumentView(document: a.$document)
        }
    }
}
import SwiftUI
import UniformTypeIdentifiers

struct Document: FileDocument {
    var text: String

    init(text: String = "Document Content") {
        self.text = text
    }

    static var readableContentTypes: [UTType] { [.plainText] }

    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents,
              let string = String(data: data, encoding: .utf8)
        else {
            throw CocoaError(.fileReadCorruptFile)
        }
        text = string
    }
    
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        let data = text.data(using: .utf8)!
        return .init(regularFileWithContents: data)
    }
}

What I've tried

I've searched the web but found nothing helpful.

I tried replacing TextEditor with TextField, and that worked for the problem. But a text editing area with only a single line is not what I want.

I tried a hacky solution which is to save the document after editing, but the application crashed with error message Performing @selector(saveDocument:) from sender __SwiftValue 0x600003efac40.


TextEditor(text: $string)
    .onChange(of: string) { _ in
        NSApp.sendAction(#selector(NSDocument.save(_:)), to: NSApp.keyWindow?.windowController?.document, from: self)
    }

I wonder whether it's possible to do that with pure SwiftUI and what would be the best way to solve the problem. Thanks in advance.

23786
  • 11
  • 3
  • Not reproduced with Xcode 13.2 / macOS 12.1. Created document app from template and replaced gendered `ContentView` with your `DocumentView` - all works fine. So verify your other code. – Asperi Dec 25 '21 at 13:24
  • @Asperi I updated my Mac to macOS 12.1 and created a document app also from the Xcode template and replaced `ContentView`. It was reproduced —— after saving the file, typing in the second `TextEditor` will cause the document to be considered as edited, displaying a dot in the red close button of the window. – 23786 Dec 25 '21 at 14:54
  • It seems that any of these conditions will mark the document as "edited": 1) any change in _any_ `TextEdit`, whether bound to the document or not 2) any actual change in the bound document variable in _any_ editable control (e.g. `TextField`). The first case doesn't seem like a right behavior, perhaps it needs to be reported as a bug. A "hacky" workaround might be to create your own multi-line text field. This problem was discussed in this [stackoverflow question](https://stackoverflow.com/questions/56471973/how-do-i-create-a-multiline-textfield-in-swiftui) – tromgy Dec 25 '21 at 15:01

0 Answers0