SwiftUI: как отключить «умные кавычки» в TextEditor
Я разрабатываю графический калькулятор на основе Python для MacOS с использованием SwiftUI.
https://github.com/snakajima/macplot
Я использую SwiftUI TextEditor в качестве редактора кода Python, но я не могу понять, как отключить умную цитату (UITextInputTraits, smartQuotesType: UITextSmartQuotesType).
VStack {
TextEditor(text: $pythonScript.script)
HStack {
Button(action: {
pythonScript.run(clear: settings.shouldClear)
}, label: {
Text("Plot")
})
Toggle("Clear", isOn: $settings.shouldClear)
}
if let errorMsg = pythonScript.errorMsg {
Text(errorMsg)
.foregroundColor(.pink)
}
}
5 ответов
После нескольких попыток я нашел следующий обходной путь. Он основан на том факте, что TextEditor реализован поверх NSTextView и меняет его поведение во всем приложении. Это некрасиво, но работает.
// HACK to work-around the smart quote issue
extension NSTextView {
open override var frame: CGRect {
didSet {
self.isAutomaticQuoteSubstitutionEnabled = false
}
}
}
Для тех, кто ищет ответ для UIKit (iOS, iPadOS) вместо AppKit (macOS), это работает для меня, используя аналогичный подход. Спасибо Сатоши!
extension UITextView {
open override var frame: CGRect {
didSet {
self.smartQuotesType = UITextSmartQuotesType.no
}
}
}
Это имеет те же недостатки, а именно то, что все текстовые поля в вашем приложении потеряют автоматические умные кавычки, но, по крайней мере, вы можете контролировать это, если вам это нужно.
Я использовал SwiftUI Introspect , чтобы отключить это для моегоTextEditor
.
TextEditor(text: $text)
.introspect(.textEditor, on: .macOS(.v14, .v13)) { nsTextView in
nsTextView.isAutomaticQuoteSubstitutionEnabled = false
nsTextView.isAutomaticDashSubstitutionEnabled = false
}
Другим решением было бы написатьNSTextView
обертка:
struct TextView: NSViewRepresentable {
@Binding var text: String
private var customizations = [(NSTextView) -> Void]()
init(text: Binding<String>) {
_text = text
}
func makeNSView(context: Context) -> NSView {
NSTextView()
}
func updateNSView(_ nsView: NSView, context: Context) {
let textView = nsView as! NSTextView
textView.string = text
customizations.forEach { $0(textView) }
}
func automaticDashSubstitutionEnabled(_ enabled: Bool) -> Self {
customized { $0.isAutomaticDashSubstitutionEnabled = enabled }
}
func automaticQuoteSubstitutionEnabled(_ enabled: Bool) -> Self {
customized { $0.isAutomaticQuoteSubstitutionEnabled = enabled }
}
func automaticSpellingCorrectionEnabled(_ enabled: Bool) -> Self {
customized { $0.isAutomaticSpellingCorrectionEnabled = enabled }
}
}
private extension TextView {
func customized(_ customization: @escaping (NSTextView) -> Void) -> Self {
var copy = self
copy.customizations.append(customization)
return copy
}
}
, который можно использовать следующим образом:
TextView(text: $myText)
.automaticDashSubstitutionEnabled(false)
.automaticQuoteSubstitutionEnabled(false)
.automaticSpellingCorrectionEnabled(false)
Я тоже боролся с этим и поэтому в конце концов исправил смарт-кавычки, заменив их прямыми кавычками при вводе текстового поля. Я знаю, что это хак, но он работает.
TextEditor(text: $Mytext)
.onChange(of: Mytext) {
newValue in
Mytext = Mytext.replacingOccurrences(of: "“", with: "\"") // replaces smart quotes
Mytext = Mytext.replacingOccurrences(of: "”", with: "\"")
Mytext = Mytext.replacingOccurrences(of: "‘", with: "'")
Mytext = Mytext.replacingOccurrences(of: "’", with: "'")
}