diff --git a/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Documents/CodeEditSourceEditorExampleDocument.swift b/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Documents/CodeEditSourceEditorExampleDocument.swift index 9e573685a..5e1c75f72 100644 --- a/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Documents/CodeEditSourceEditorExampleDocument.swift +++ b/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Documents/CodeEditSourceEditorExampleDocument.swift @@ -8,10 +8,14 @@ import SwiftUI import UniformTypeIdentifiers -struct CodeEditSourceEditorExampleDocument: FileDocument { - var text: String +struct CodeEditSourceEditorExampleDocument: FileDocument, @unchecked Sendable { + enum DocumentError: Error { + case failedToEncode + } + + var text: NSTextStorage - init(text: String = "") { + init(text: NSTextStorage = NSTextStorage(string: "")) { self.text = text } @@ -25,11 +29,31 @@ struct CodeEditSourceEditorExampleDocument: FileDocument { guard let data = configuration.file.regularFileContents else { throw CocoaError(.fileReadCorruptFile) } - text = String(decoding: data, as: UTF8.self) + var nsString: NSString? + NSString.stringEncoding( + for: data, + encodingOptions: [ + // Fail if using lossy encoding. + .allowLossyKey: false, + // In a real app, you'll want to handle more than just this encoding scheme. Check out CodeEdit's + // implementation for a more involved solution. + .suggestedEncodingsKey: [NSUTF8StringEncoding], + .useOnlySuggestedEncodingsKey: true + ], + convertedString: &nsString, + usedLossyConversion: nil + ) + if let nsString { + self.text = NSTextStorage(string: nsString as String) + } else { + fatalError("Failed to read file") + } } func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper { - let data = Data(text.utf8) + guard let data = (text.string as NSString?)?.data(using: NSUTF8StringEncoding) else { + throw DocumentError.failedToEncode + } return .init(regularFileWithContents: data) } } diff --git a/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/ContentView.swift b/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/ContentView.swift index 8a42a5f1a..4c896888b 100644 --- a/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/ContentView.swift +++ b/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/ContentView.swift @@ -39,7 +39,7 @@ struct ContentView: View { var body: some View { GeometryReader { proxy in CodeEditSourceEditor( - $document.text, + document.text, language: language, theme: theme, font: font, diff --git a/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/StatusBar.swift b/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/StatusBar.swift index 779f5cd35..d471706f9 100644 --- a/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/StatusBar.swift +++ b/Example/CodeEditSourceEditorExample/CodeEditSourceEditorExample/Views/StatusBar.swift @@ -30,7 +30,7 @@ struct StatusBar: View { var body: some View { HStack { Menu { - IndentPicker(indentOption: $indentOption, enabled: document.text.isEmpty) + IndentPicker(indentOption: $indentOption, enabled: document.text.length == 0) .buttonStyle(.borderless) Toggle("Wrap Lines", isOn: $wrapLines) Toggle("Show Minimap", isOn: $showMinimap) @@ -106,8 +106,8 @@ struct StatusBar: View { guard let fileURL else { return nil } return CodeLanguage.detectLanguageFrom( url: fileURL, - prefixBuffer: document.text.getFirstLines(5), - suffixBuffer: document.text.getLastLines(5) + prefixBuffer: document.text.string.getFirstLines(5), + suffixBuffer: document.text.string.getLastLines(5) ) }