Document is not being marked dirty when element is being changed programmatically
What is wrong with this SwiftUI code?
When the button "Reset Text" is pressed the document data is changed (as seen in the debugger), but the view is not updated.
If the document is then saved, the modified data is not saved. The method "func fileWrapper" is not called because it does not think that the field "text" has changed.
If characters are typed in the TextEditor so the field is dirty and then saved, the data is saved.
If characters are types in the TextEditor so the field is dirty, then the "Reset Text" button pressed, the TextEditor view is not updated, but the "Reset Text" is saved.
If I wait a while 1 to 3 minutes, the TextEditor will sometimes update to the new text.
import SwiftUI
import UniformTypeIdentifiers
@main
struct DocumentAppApp: App {
var body: some Scene {
DocumentGroup(newDocument: DocumentAppDocument()) { file in
ContentView(document: file.$document)
}
}
}
extension UTType {
static var exampleText: UTType {
UTType(importedAs: "com.example.plain-text")
}
}
class DocumentAppDocument: ObservableObject, FileDocument {
@Published var text: String
init(text: String = "This is some text") {
self.text = text
}
static var readableContentTypes: [UTType] { [.exampleText] }
required 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)
}
}
struct ContentView: View {
@Binding var document: DocumentAppDocument
var body: some View {
VStack {
TextEditor(text: $document.text)
Button(action: {
// document.objectWillChange.send()
document.text = "Reset Text"
}, label: { Text("Reset Text") })
.frame(width: 200, height: 50)
.border(Color.black)
.padding()
}
}
}
I tried added a call to document.objectWillChange.send() and it made no difference.
I tried as both a struct and a class
I've tried various combinations of @State, @StateObject and @Binding.
It looks like I could call .save on the DocumentGroup, but I couldn't figure out how to get ahold of it.
Test case
Create a new document.
Type in some text -> test is there
Save document.
Open document -> text is there.
Press "Reset Text" Button. Nothing happens.
Save.
Open -> previous text is there.
Type some text, press button -> nothing happens.
Save.
Open -> "Reset Text: text is present.
Comments
Post a Comment