如何添加 onCommit、isEditing 以及自定义绑定到自定义文本视图的能力?
How to add onCommit, isEditing, and ability to have a custom binding to a custom textview?
提供以下 UIViewRepresentable isEditing 和 onCommit 属性的最佳方法是什么?我希望它在 SwiftUI 中调用 TextFields 时具有完全相同的功能(您可以在其中添加代码以在按下 return 键 [onCommit] 或单击文本字段时执行操作 [isEditing])
struct TextView: UIViewRepresentable {
@Binding var text: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let myTextView = UITextView()
myTextView.delegate = context.coordinator
myTextView.font = UIFont(name: "HelveticaNeue", size: 16)
myTextView.isScrollEnabled = true
myTextView.isEditable = true
myTextView.isUserInteractionEnabled = true
myTextView.backgroundColor = UIColor(white: 0.0, alpha: 0.00)
myTextView.textColor = UIColor.black
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
class Coordinator : NSObject, UITextViewDelegate {
var parent: TextView
init(_ uiTextView: TextView) {
self.parent = uiTextView
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.resignFirstResponder()
}
return true
}
func textViewDidChange(_ textView: UITextView) {
print("text now: \(String(describing: textView.text!))")
self.parent.text = textView.text
}
}
}
旁注:我不确定为什么,但我传入的绑定变量并没有改变实际值。我知道是因为我使用 get/set 属性设置了自定义绑定,并且该集合未打印该值。 (这个值应该是传入textview的文本)
let binding = Binding<String>(get: {
self.bindingVariableName
}, set: {
print("set the value")
self.bindingVariableName = [=11=]
}
)
onCommit
您可以将函数作为变量传递,使它们在正确的位置执行,例如:
struct TextView: UIViewRepresentable {
@Binding var text: String
var onCommit: ()->()
...
}
... {
...
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.resignFirstResponder()
parent.onCommit() // <- execute here
}
return true
}
}
并像这样使用它:
TextView(text: $text, onCommit: {
print("Committed")
})
可以应用类似的检测变化的方法
编辑
如果您使用的是 SwiftUI 2.0,您可以使用类似 onCommit
我上面解释的 或 的方法,您可以使用 .onChange
修饰符观察变化(如果实际值从 SwiftUI
一侧发生变化),例如:
struct ContentView: View {
@State var text: String = ""
var body: some View {
TextView(text: $text)
.onChange(of: text) { value in
print("text now: " + text)
}
}
}
更新实际 @Binding
值:
您需要通过在 coordinator
:
中实现此功能来更新 UIKit
中的 text
func textViewDidChange(_ textView: UITextView) {
parent.text = textView.text
}
然后实际绑定变量在文本字段的文本更改事件上得到更新。
奖励
使用此方法,您还可以将配置步骤转发到SwiftUI
端。所以重构后的完整工作代码如下:
struct ContentView: View {
@State var text: String = ""
var body: some View {
TextView(text: $text) { // Configuring the text field
[=14=].font = UIFont(name: "HelveticaNeue", size: 16)
[=14=].isScrollEnabled = true
[=14=].isEditable = true
[=14=].isUserInteractionEnabled = true
[=14=].backgroundColor = UIColor(white: 0.0, alpha: 0.00)
[=14=].textColor = UIColor.black
}
onCommit: { // Detecting the commit
print("Committed with text: " + text)
}
.onChange(of: text) { value in // The native way to detect changes of a State
print("text now: " + text)
}
}
}
struct TextView: UIViewRepresentable {
@Binding var text: String
var configurate: (UITextView) -> ()
var onCommit: ()->()
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let myTextView = UITextView()
configurate(myTextView) // Forwarding the configuring step
myTextView.delegate = context.coordinator
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
class Coordinator: NSObject, UITextViewDelegate {
var parent: TextView
init(_ uiTextView: TextView) {
self.parent = uiTextView
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.resignFirstResponder()
parent.onCommit() // Execute the passed `onCommit` method here
}
return true
}
func textViewDidChange(_ textView: UITextView) {
parent.text = textView.text // Update the actual variable
}
}
}
提供以下 UIViewRepresentable isEditing 和 onCommit 属性的最佳方法是什么?我希望它在 SwiftUI 中调用 TextFields 时具有完全相同的功能(您可以在其中添加代码以在按下 return 键 [onCommit] 或单击文本字段时执行操作 [isEditing])
struct TextView: UIViewRepresentable {
@Binding var text: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let myTextView = UITextView()
myTextView.delegate = context.coordinator
myTextView.font = UIFont(name: "HelveticaNeue", size: 16)
myTextView.isScrollEnabled = true
myTextView.isEditable = true
myTextView.isUserInteractionEnabled = true
myTextView.backgroundColor = UIColor(white: 0.0, alpha: 0.00)
myTextView.textColor = UIColor.black
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
class Coordinator : NSObject, UITextViewDelegate {
var parent: TextView
init(_ uiTextView: TextView) {
self.parent = uiTextView
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.resignFirstResponder()
}
return true
}
func textViewDidChange(_ textView: UITextView) {
print("text now: \(String(describing: textView.text!))")
self.parent.text = textView.text
}
}
}
旁注:我不确定为什么,但我传入的绑定变量并没有改变实际值。我知道是因为我使用 get/set 属性设置了自定义绑定,并且该集合未打印该值。 (这个值应该是传入textview的文本)
let binding = Binding<String>(get: {
self.bindingVariableName
}, set: {
print("set the value")
self.bindingVariableName = [=11=]
}
)
onCommit
您可以将函数作为变量传递,使它们在正确的位置执行,例如:
struct TextView: UIViewRepresentable {
@Binding var text: String
var onCommit: ()->()
...
}
... {
...
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.resignFirstResponder()
parent.onCommit() // <- execute here
}
return true
}
}
并像这样使用它:
TextView(text: $text, onCommit: {
print("Committed")
})
可以应用类似的检测变化的方法
编辑
如果您使用的是 SwiftUI 2.0,您可以使用类似 onCommit
我上面解释的 或 的方法,您可以使用 .onChange
修饰符观察变化(如果实际值从 SwiftUI
一侧发生变化),例如:
struct ContentView: View {
@State var text: String = ""
var body: some View {
TextView(text: $text)
.onChange(of: text) { value in
print("text now: " + text)
}
}
}
更新实际 @Binding
值:
您需要通过在 coordinator
:
UIKit
中的 text
func textViewDidChange(_ textView: UITextView) {
parent.text = textView.text
}
然后实际绑定变量在文本字段的文本更改事件上得到更新。
奖励
使用此方法,您还可以将配置步骤转发到SwiftUI
端。所以重构后的完整工作代码如下:
struct ContentView: View {
@State var text: String = ""
var body: some View {
TextView(text: $text) { // Configuring the text field
[=14=].font = UIFont(name: "HelveticaNeue", size: 16)
[=14=].isScrollEnabled = true
[=14=].isEditable = true
[=14=].isUserInteractionEnabled = true
[=14=].backgroundColor = UIColor(white: 0.0, alpha: 0.00)
[=14=].textColor = UIColor.black
}
onCommit: { // Detecting the commit
print("Committed with text: " + text)
}
.onChange(of: text) { value in // The native way to detect changes of a State
print("text now: " + text)
}
}
}
struct TextView: UIViewRepresentable {
@Binding var text: String
var configurate: (UITextView) -> ()
var onCommit: ()->()
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let myTextView = UITextView()
configurate(myTextView) // Forwarding the configuring step
myTextView.delegate = context.coordinator
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
class Coordinator: NSObject, UITextViewDelegate {
var parent: TextView
init(_ uiTextView: TextView) {
self.parent = uiTextView
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.resignFirstResponder()
parent.onCommit() // Execute the passed `onCommit` method here
}
return true
}
func textViewDidChange(_ textView: UITextView) {
parent.text = textView.text // Update the actual variable
}
}
}