This does indeed appear to be a sad oversight from Apple...
However thankfully there are workarounds...
import Introspect
extension UITextField {
func addDoneButton() {
self.keyboardAppearance = .light
let keyboardToolbar = UIToolbar()
keyboardToolbar.sizeToFit()
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done,
target: self, action: #selector(resignFirstResponder))
keyboardToolbar.items = [flexibleSpace, doneButton]
self.inputAccessoryView = keyboardToolbar
}
}
extension View {
func addDoneButton() -> some View {
let helper = MainViewHelper()
let customise: (UITextView) -> () = { uiTextView in
let toolBar = UIToolbar(frame: CGRect(x: 0.0,
y: 0.0,
width: UIScreen.main.bounds.size.width,
height: 44.0))//1
let flexible = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let barButton = UIBarButtonItem(title: "Done", style: .plain, target: uiTextView, action: #selector(helper.close))
toolBar.setItems([flexible, barButton], animated: false)//4
uiTextView.inputAccessoryView = toolBar
uiTextView.keyboardAppearance = .light
}
return introspect(selector: TargetViewSelector.siblingContaining, customize: customise)
}
}
class MainViewHelper {
@objc func close() {
}
}
extension UITextView {
func addDoneButton(title: String) {
let textView = self
let toolBar = UIToolbar(frame: CGRect(x: 0.0,
y: 0.0,
width: UIScreen.main.bounds.size.width,
height: 44.0))
let flexible = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let barButton = UIBarButtonItem(title: title, style: .plain, target: textView, action: #selector(close))
toolBar.setItems([flexible, barButton], animated: false)//4
self.inputAccessoryView = toolBar
self.keyboardAppearance = .light
}
@objc func close() {
self.resignFirstResponder()
}
}