Post not yet marked as solved
Post marked as unsolved with 0 replies, 1,477 views
Hi, I need to create a multiline editable text in SwiftUI and also have ability to insert some other text at cursor position. I have created this test application to see how it could work and ended up with this. But it doesn't really work how it should and I am stuck.
You should be able to write anything into the main text field and also when you press the button, the text from the textfield should be inserted into the main text at your cursor location.
Any help would be much appreciated.
//
//	InsertTextTestApp.swift
//	InsertTextTest
//
//	Created by Matej Volkmer on 04.02.2021.
//
import SwiftUI
@main
struct InsertTextTestApp: App {
		var body: some Scene {
				WindowGroup {
						ContentView()
				}
		}
}
struct ContentView: View {
		@State var text = "Lorem ipsum dolor sit amet."
		@State var insertText = ""
		@State var fieldText = ""
		
		var body: some View {
				VStack {
						CustomTextField(text: $text, insertText: $insertText)
						
						TextField("Text to insert", text: $fieldText)
						
						Button("Insert") {
								insertText = fieldText
						}
						.keyboardShortcut(.tab, modifiers: .control)
				}
				.frame(width: 400, height: 400)
		}
}
struct CustomTextField: NSViewRepresentable {
		@Binding var text: String
		@Binding var insertText: String
		
		func makeNSView(context: NSViewRepresentableContext<Self>) -> NSTextView {
				let NSView = NSTextView()
				
				NSView.isEditable = true
				NSView.isSelectable = true
				NSView.delegate = context.coordinator
				
				return NSView
		}
		func updateNSView(_ NSView: NSTextView, context: NSViewRepresentableContext<Self>) {
				if NSView.string != self.text {
						NSView.string = self.text
				}
				
				NSView.insertText(self.insertText, replacementRange: NSView.selectedRanges.first!.rangeValue)
		}
		func makeCoordinator() -> Coordinator {
				return Coordinator(text: $text)
		}
		final class Coordinator : NSObject, NSTextViewDelegate {
				var text: Binding<String>
				
				init(text: Binding<String>) {
						self.text = text
				}
				
				func textViewDidChange(_ NSView: NSTextView) {
					 text.wrappedValue = NSView.string
				}
		}
}