UITextView dynamically change height based on content? - swift

I have been stumped by this issue for a bit so I hoping to get some help. I have a SwiftUI application that is using UITextView but when I put content in it the text does not wrap. This SwiftUI view I am making both displays and edits text but it currently works for neither.
The text in the second box is much longer but the height does not change.
func makeUIView(context: Context) -> UITextView {
view.isScrollEnabled = false
view.isEditable = editable
view.isUserInteractionEnabled = true
view.contentInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
view.text = self.text
// For debugging
view.layer.borderColor = UIColor.black.cgColor
view.layer.borderWidth = 1.0
var fontPref = UIFont.preferredFont(forTextStyle: render.font)
if render.bold && render.italic {
fontPref = fontPref.bolditalic()
} else if render.bold {
fontPref = fontPref.bold()
} else if render.italic {
fontPref = fontPref.italic()
}
view.font = fontPref
view.textColor = render.color
view.textAlignment = render.align
view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
view.textContainer.lineBreakMode = .byWordWrapping
view.delegate = context.coordinator
return view
}
I have tried a few solutions but none of them are working for my use case.
Thanks!

here is a working custom textview that wraps the text and adjusts height:
import SwiftUI
struct NoteTextView: UIViewRepresentable {
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
#Binding var text: String
var onEndEditing: () -> Void
typealias UIViewType = UITextView
var configuration = { (view: UIViewType) in }
func makeUIView(context: UIViewRepresentableContext<Self>) -> UIViewType {
let textField = UIViewType()
textField.delegate = context.coordinator
textField.font = UIFont.preferredFont(forTextStyle: .body)
textField.text = text
textField.isScrollEnabled = true
textField.isEditable = true
textField.isUserInteractionEnabled = true
return textField
}
func updateUIView(_ uiView: UIViewType, context: UIViewRepresentableContext<Self>) {
uiView.text = text
configuration(uiView)
}
class Coordinator : NSObject, UITextViewDelegate {
var parent: NoteTextView
init(_ uiTextView: NoteTextView) {
self.parent = uiTextView
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
return true
}
func textViewDidChange(_ textView: UITextView) {
self.parent.text = textView.text
}
}
}

Related

How can I override paste so I can paste images in a UITextView?

I am trying to paste images in a UITextView so I can have text + images in the same UITextView, I read somewhere else I need to override the paste function as it doesn't accept images for text, but I did that but I got an error "Method does not override any method from its superclass"
any idea how to override paste so I can past images in a TextView?
struct TextView: UIViewRepresentable {
#Binding var text: String
#Binding var textStyle: UIFont.TextStyle
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
textView.font = UIFont.preferredFont(forTextStyle: textStyle)
textView.autocapitalizationType = .sentences
textView.isSelectable = true
textView.isUserInteractionEnabled = true
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
uiView.font = UIFont.preferredFont(forTextStyle: textStyle)
}
func makeCoordinator() -> Coordinator {
Coordinator($text)
}
class Coordinator: NSObject, UITextViewDelegate {
var text: Binding<String>
init(_ text: Binding<String>) {
self.text = text
}
func textViewDidChange(_ textView: UITextView) {
self.text.wrappedValue = textView.text
}
override func paste(_ sender: Any?) {
let textAttachment = NSTextAttachment()
textAttachment.image = UIPasteboard.general.image
//attributedText = NSAttributedString(attachment: textAttachment)
let attributedText = NSAttributedString(attachment: textAttachment)
}
}
}

How to make TextField exit its editing mode

I attempted to bind a isEditing variable to under my UIViewRepresentable which is controlled by a close button in my SwiftUI View.
Under the UIViewRepresentable, I create a UITextfield and what I want to accomplish here is to tap the close button which triggers the isEditing variable and reset the UITextfield to make it leave edit mode. I tried to detect this change under the updateUIView
struct SearchBarViewController: UIViewRepresentable {
let searchEngine = SearchEngine()
let textField = LeftPaddedTextField(frame: .zero)
#Binding var text: String
#Binding var searchArray:[String]
#Binding var isEditing: Bool
func makeUIView(context: UIViewRepresentableContext<SearchBarViewController>) -> UITextField {
textField.delegate = context.coordinator
textField.textColor = UIColor.gray
textField.placeholder = "Where are you going?"
textField.layer.cornerRadius = 20
//textField.layer.borderWidth = 1.5
textField.layer.borderColor = UIColor.tertiaryLabel.cgColor
textField.backgroundColor = UIColor.systemGray6
textField.borderStyle = .none
textField.addTarget(context.coordinator, action: #selector(context.coordinator.textFieldDidChange), for: .editingChanged)
textField.clearButtonMode = .whileEditing
searchEngine.delegate = context.coordinator
return textField
}
func updateUIView(_ uiViewController: UITextField, context: UIViewRepresentableContext<SearchBarViewController>) {
if isEditing {
return
}
print("update is called")
if !isEditing {
//textField.resignFirstResponder()
textField.endEditing(true)
}
}
func makeCoordinator() -> SearchBarViewController.Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject, UITextFieldDelegate, SearchEngineDelegate {
var control: SearchBarViewController
init(_ control: SearchBarViewController) {
self.control = control
}
func resultsUpdated(searchEngine: SearchEngine) {
self.control.searchArray = []
if !searchEngine.items.isEmpty {
for i in searchEngine.items {
if let description = i.descriptionText {
self.control.searchArray.append(description)
}
}
}
print()
}
func resolvedResult(result: SearchResult) {
print()
}
func searchErrorHappened(searchError: SearchError) {
print("Error during search: \(searchError)")
}
func textFieldDidBeginEditing(_ textField: UITextField) {
self.control.isEditing = true
}
func textFieldShouldClear(_ textField: UITextField) -> Bool {
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.control.textField.resignFirstResponder()
self.control.isEditing = false
return true
}
// Update model.text when textField.text is changed
#objc func textFieldDidChange() {
if let text = self.control.textField.text {
self.control.text = text
}
if self.control.textField.text != "" {
if let text = control.textField.text {
control.searchEngine.query = text
}
} else {
self.control.searchArray = []
}
}
}
}
And here is the code of the outside view:
struct SearchBarView: View {
#State var isEditing = false
...
var body: some View {
Button(action: {
self.isEditing = false
self.text = ""
}) {
Text("Return")
}
SearchBarViewController(text: $text, searchArray: $searchArray, isEditing: $isEditing)
}
}
But the problem is it doesn't work. After I click the close button the UITextField doesn't exit its edit mode and I still can type. So I am asking whether there is a way to accomplish it.
Thanks for your help in advance.
Try to use passed in instance of text field
func updateUIView(_ uiTextField: UITextField, context: UIViewRepresentableContext<SearchBarViewController>) {
if isEditing {
return
}
print("update is called")
if !isEditing {
uiTextField.resignFirstResponder() // << here !!
// uiTextField.endEditing(true)
}
}

UITextView with Adjustable Font Size

I tried to make an editable uitextview with centered text that can have a maximum of 2 lines and that automatically adjusts its font size in order to fit its text within a fixed width and height.
My solution: Type some text in a UITextView, automatically copy that text and paste it in a uilabel that itself automatically adjusts its font size perfectly, and then retrieve the newly adjusted font size of the uilabel and set that size on the UITextView text.
I have spent about a month on this and repeatedly failed. I can't find a way to make it work. My attempted textview below glitches some letters out and hides large portions of out-of-bounds text instead of resizing everything. Please help me stack overflow Gods.
My attempt:
import UIKit
class TextViewViewController: UIViewController{
private let editableUITextView: UITextView = {
let tv = UITextView()
tv.font = UIFont.systemFont(ofSize: 20)
tv.text = "Delete red text, and type here"
tv.backgroundColor = .clear
tv.textAlignment = .center
tv.textContainer.maximumNumberOfLines = 2
tv.textContainer.lineBreakMode = .byWordWrapping
tv.textColor = .red
return tv
}()
private let correctTextSizeLabel: UILabel = {
let tv = UILabel()
tv.font = UIFont.systemFont(ofSize: 20)
tv.backgroundColor = .clear
tv.text = "This is properly resized"
tv.adjustsFontSizeToFitWidth = true
tv.lineBreakMode = .byTruncatingTail
tv.numberOfLines = 2
tv.textAlignment = .center
tv.textColor = .green
return tv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
view.addSubview(correctTextSizeLabel)
view.addSubview(editableUITextView)
editableUITextView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
editableUITextView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
editableUITextView.heightAnchor.constraint(equalToConstant: 150).isActive = true
editableUITextView.widthAnchor.constraint(equalToConstant: 150).isActive = true
editableUITextView.translatesAutoresizingMaskIntoConstraints = false
editableUITextView.delegate = self
correctTextSizeLabel.leftAnchor.constraint(equalTo: editableUITextView.leftAnchor).isActive = true
correctTextSizeLabel.rightAnchor.constraint(equalTo: editableUITextView.rightAnchor).isActive = true
correctTextSizeLabel.topAnchor.constraint(equalTo: editableUITextView.topAnchor).isActive = true
correctTextSizeLabel.bottomAnchor.constraint(equalTo: editableUITextView.bottomAnchor).isActive = true
correctTextSizeLabel.translatesAutoresizingMaskIntoConstraints = false
editableUITextView.isScrollEnabled = false
}
func getApproximateAdjustedFontSizeOfLabel(label: UILabel) -> CGFloat {
if label.adjustsFontSizeToFitWidth == true {
var currentFont: UIFont = label.font
let originalFontSize = currentFont.pointSize
var currentSize: CGSize = (label.text! as NSString).size(withAttributes: [NSAttributedString.Key.font: currentFont])
while currentSize.width > label.frame.size.width * 2 && currentFont.pointSize > (originalFontSize * label.minimumScaleFactor) {
currentFont = currentFont.withSize(currentFont.pointSize - 1)
currentSize = (label.text! as NSString).size(withAttributes: [NSAttributedString.Key.font: currentFont])
}
return currentFont.pointSize
} else {
return label.font.pointSize
}
}
}
//MARK: - UITextViewDelegate
extension TextViewViewController : UITextViewDelegate {
private func textViewShouldBeginEditing(_ textView: UITextView) {
textView.becomeFirstResponder()
}
func textViewDidBeginEditing(_ textView: UITextView) {
}
func textViewDidEndEditing(_ textView: UITextView) {
}
func textViewDidChange(_ textView: UITextView) {
textView.becomeFirstResponder()
self.correctTextSizeLabel.text = textView.text
self.correctTextSizeLabel.isHidden = false
let estimatedTextSize = self.getApproximateAdjustedFontSizeOfLabel(label: self.correctTextSizeLabel)
print("estimatedTextSize: ",estimatedTextSize)
self.editableUITextView.font = UIFont.systemFont(ofSize: estimatedTextSize)
}
}
UITextField's have the option to automatically adjust font size to fit a fixed width but they only allow 1 line of text, I need it to have a maximum of 2. UILabel's solve this problem perfectly but they aren't editable.
After some searching, this looks like it will be very difficult to get working as desired.
This doesn't directly answer your question, but it may be an option:
Here's the example code:
class TestInputViewController: UIViewController {
let testLabel: InputLabel = InputLabel()
override func viewDidLoad() {
super.viewDidLoad()
let instructionLabel = UILabel()
instructionLabel.textAlignment = .center
instructionLabel.text = "Tap yellow label to edit..."
let centeringFrameView = UIView()
// label properties
let fnt: UIFont = .systemFont(ofSize: 32.0)
testLabel.isUserInteractionEnabled = true
testLabel.font = fnt
testLabel.adjustsFontSizeToFitWidth = true
testLabel.minimumScaleFactor = 0.25
testLabel.numberOfLines = 2
testLabel.setContentHuggingPriority(.required, for: .vertical)
let minLabelHeight = ceil(fnt.lineHeight)
// so we can see the frames
centeringFrameView.backgroundColor = .red
testLabel.backgroundColor = .yellow
[centeringFrameView, instructionLabel, testLabel].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
view.addSubview(instructionLabel)
view.addSubview(centeringFrameView)
centeringFrameView.addSubview(testLabel)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// instruction label centered at top
instructionLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
instructionLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
// centeringFrameView 20-pts from instructionLabel bottom
centeringFrameView.topAnchor.constraint(equalTo: instructionLabel.bottomAnchor, constant: 20.0),
// Leading / Trailing with 20-pts "padding"
centeringFrameView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
centeringFrameView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
// test label centered vertically in centeringFrameView
testLabel.centerYAnchor.constraint(equalTo: centeringFrameView.centerYAnchor, constant: 0.0),
// Leading / Trailing with 20-pts "padding"
testLabel.leadingAnchor.constraint(equalTo: centeringFrameView.leadingAnchor, constant: 20.0),
testLabel.trailingAnchor.constraint(equalTo: centeringFrameView.trailingAnchor, constant: -20.0),
// height will be zero if label has no text,
// so give it a min height of one line
testLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: minLabelHeight),
// centeringFrameView height = 3 * minLabelHeight
centeringFrameView.heightAnchor.constraint(equalToConstant: minLabelHeight * 3.0)
])
// to handle user input
testLabel.editCallBack = { [weak self] str in
guard let self = self else { return }
self.testLabel.text = str
}
testLabel.doneCallBack = { [weak self] in
guard let self = self else { return }
// do something when user taps done / enter
}
let t = UITapGestureRecognizer(target: self, action: #selector(self.labelTapped(_:)))
testLabel.addGestureRecognizer(t)
}
#objc func labelTapped(_ g: UITapGestureRecognizer) -> Void {
testLabel.becomeFirstResponder()
testLabel.inputContainerView.theTextView.text = testLabel.text
testLabel.inputContainerView.theTextView.becomeFirstResponder()
}
}
class InputLabel: UILabel {
var editCallBack: ((String) -> ())?
var doneCallBack: (() -> ())?
override var canBecomeFirstResponder: Bool {
return true
}
override var canResignFirstResponder: Bool {
return true
}
override var inputAccessoryView: UIView? {
get { return inputContainerView }
}
lazy var inputContainerView: CustomInputAccessoryView = {
let customInputAccessoryView = CustomInputAccessoryView(frame: .zero)
customInputAccessoryView.backgroundColor = .blue
customInputAccessoryView.editCallBack = { [weak self] str in
guard let self = self else { return }
self.editCallBack?(str)
}
customInputAccessoryView.doneCallBack = { [weak self] in
guard let self = self else { return }
self.resignFirstResponder()
}
return customInputAccessoryView
}()
}
class CustomInputAccessoryView: UIView, UITextViewDelegate {
var editCallBack: ((String) -> ())?
var doneCallBack: (() -> ())?
let theTextView: UITextView = {
let tv = UITextView()
tv.isScrollEnabled = false
tv.font = .systemFont(ofSize: 16)
tv.autocorrectionType = .no
tv.returnKeyType = .done
return tv
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.white
autoresizingMask = [.flexibleHeight, .flexibleWidth]
addSubview(theTextView)
theTextView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// constraint text view with 8-pts "padding" on all 4 sides
theTextView.topAnchor.constraint(equalTo: topAnchor, constant: 8),
theTextView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8),
theTextView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8),
theTextView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8),
])
theTextView.delegate = self
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.resignFirstResponder()
doneCallBack?()
}
return true
}
func textViewDidChange(_ textView: UITextView) {
editCallBack?(textView.text ?? "")
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var intrinsicContentSize: CGSize {
return .zero
}
}

TextView expands parent view causing text to be hidden

My problem is shown in the photo below:
I have tried using .fixedSize(horizontal:vertical) on the parent view and the textfield and no positive results.
TheTextField:
struct TheTextField: UIViewRepresentable {
#Binding var text : String
#Binding var placeholder : String
func makeCoordinator() -> TheTextField.Coordinator {
return TheTextField.Coordinator(parent1: self)
}
func makeUIView(context: UIViewRepresentableContext<TheTextField>) -> UITextView {
let tview = UITextView()
tview.isEditable = true
tview.isUserInteractionEnabled = true
tview.isScrollEnabled = false
tview.text = placeholder
tview.textColor = .gray
tview.font = .systemFont(ofSize: 20)
tview.delegate = context.coordinator
return tview
}
func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<TheTextField>) {
}
class Coordinator : NSObject, UITextViewDelegate {
var parent : TheTextField
init(parent1 : TheTextField) {
parent = parent1
}
func textViewDidChange(_ textView: UITextView) {
self.parent.text = textView.text
}
func textViewDidBeginEditing(_ textView: UITextView) {
textView.text = ""
textView.textColor = .label
}
}
}
I want the textview to not expand and move the cursor to the next line, instead of messing up the parent's view.
Example:
Divider()
TheTextField(text: self.$imageToUpload.textCaption, placeholder: self.$placeholder).padding(.horizontal)
Spacer()
import SwiftUI
struct UITextViewWrapper: UIViewRepresentable {
#Binding var text : String
#Binding var calculatedHeight: CGFloat
func makeCoordinator() -> UITextViewWrapper.Coordinator {
return UITextViewWrapper.Coordinator(text: $text, height: $calculatedHeight)
}
func makeUIView(context: UIViewRepresentableContext<UITextViewWrapper>) -> UITextView {
let tview = UITextView()
tview.isEditable = true
tview.isUserInteractionEnabled = true
tview.isScrollEnabled = false
tview.textColor = .gray
tview.font = .systemFont(ofSize: 20)
tview.delegate = context.coordinator
tview.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
return tview
}
func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<UITextViewWrapper>) {
if uiView.text != self.text {
uiView.text = self.text
}
if uiView.window != nil, uiView.isFirstResponder {
uiView.becomeFirstResponder()
}
}
static func recalculateHeight(view: UIView, result: Binding<CGFloat>){
let newSize = view.sizeThatFits(CGSize(width: view.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
if result.wrappedValue != newSize.height {
DispatchQueue.main.async {
result.wrappedValue = newSize.height // !! must be called asynchronously
}
}
}
class Coordinator : NSObject, UITextViewDelegate {
var text : Binding<String>
var calculatedHeight : Binding<CGFloat>
init(text: Binding<String>, height: Binding<CGFloat>) {
self.text = text
self.calculatedHeight = height
}
func textViewDidChange(_ textView: UITextView) {
text.wrappedValue = textView.text
UITextViewWrapper.recalculateHeight(view: textView, result: calculatedHeight)
}
func textViewDidBeginEditing(_ textView: UITextView) {
textView.text = ""
textView.textColor = .label
}
}
}
I added functionality for changing the height of the dynamically depending on the length of the text per suggestion by Asperi.
You can easily edit label property from .storyboard file of our project.
Change lines to 0 and line break property to your desired type and then you can have as many lines as you want your label to have.Check this image to see what I'm saying

swiftUI how to have search button on keyboard

In SwiftUI I have a simple search TextField where the user type something to be searched and a Button search.
I just want to add the option to have the button Search in the lower right corner of the Keyboard (I saw it in some application)
how can I do that?
iOS 15
You can change the return key for each textField with a simple modifier called: .submitLabel that takes the return key type and you should pass .search. Take a look at the following example:
Also, as you can see, you can have a callback to handle the return key press action just like the old textFieldShouldReturn function that is accessible by '.onSubmit' modifier.
If I understand correctly you want to change the UIReturnKeyType.
In that case you have to use UIKit since there isn't yet any option to change the type of return key in SwiftUI.
To do this, you have to make a custom TextField using UIIKit and then modify it the way you like.
Also keep in mind that the UIReturnKeyType enum is under discussion and may replace with a different implementation.
// MARK: Custom TextField
struct TextFieldTyped: UIViewRepresentable {
let keyboardType: UIKeyboardType
let returnVal: UIReturnKeyType
let tag: Int
#Binding var text: String
#Binding var isfocusAble: [Bool]
func makeUIView(context: Context) -> UITextField {
let textField = UITextField(frame: .zero)
textField.keyboardType = self.keyboardType
textField.returnKeyType = self.returnVal
textField.tag = self.tag
textField.delegate = context.coordinator
textField.autocorrectionType = .no
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
if isfocusAble[tag] {
uiView.becomeFirstResponder()
} else {
uiView.resignFirstResponder()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: TextFieldTyped
init(_ textField: TextFieldTyped) {
self.parent = textField
}
func updatefocus(textfield: UITextField) {
textfield.becomeFirstResponder()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if parent.tag == 0 {
parent.isfocusAble = [false, true]
parent.text = textField.text ?? ""
} else if parent.tag == 1 {
parent.isfocusAble = [false, false]
parent.text = textField.text ?? ""
}
return true
}
}
}
And you can use it like this:
(Change the returnVal to .search in your case.)
struct CustomeKT: View {
#State var myTextForTX = ""
#State var focused: [Bool] = [false, true]
var body: some View {
TextFieldTyped(keyboardType: .default, returnVal: .search, tag: 0, text: self.$myTextForTX, isfocusAble: self.$focused)
}
}
Simple Use SearchTextField.swift
import SwiftUI
import UIKit
class UIKitTextField: UITextField, UITextFieldDelegate {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
delegate = self
}
required override init(frame: CGRect) {
super.init(frame: frame)
delegate = self
self.setContentHuggingPriority(.defaultHigh, for: .vertical)
}
var action:(() -> Void)? = nil
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.action?()
if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {
nextField.becomeFirstResponder()
} else {
textField.resignFirstResponder()
return true;
}
return false
}
}
struct SearchTextField : UIViewRepresentable {
#Binding var text: String
var action:() -> Void
func makeCoordinator() -> SearchTextField.Coordinator {
return Coordinator(value: self)
}
class Coordinator: NSObject,UITextFieldDelegate {
var parent:SearchTextField
init(value: SearchTextField) {
self.parent = value
}
#objc func textFieldEditingChanged(_ sender: UIKitTextField) {
self.parent.text = sender.text ?? ""
}
}
func makeUIView(context: Context) -> UIKitTextField {
let textfield = UIKitTextField(frame: .zero)
textfield.addTarget(context.coordinator, action: #selector(Coordinator.textFieldEditingChanged(_:)), for: .editingChanged)
textfield.text = self.text
textfield.placeholder = "search"
textfield.borderStyle = .none
textfield.returnKeyType = .search
textfield.action = self.action
return textfield
}
func updateUIView(_ uiView: UIKitTextField,
context: Context) {
uiView.text = self.text
}
}
Use :
SearchTextField(text: self.$searchKey) {
self.search(key: self.searchKey)
// or...
}