#swiftui #uikit #uiviewrepresentable
#swiftui #uikit #uiviewrepresentable
Вопрос:
Я создал текстовое представление SwiftUI на основе UITextView, используя UIViewRepresentable (см. код ниже). Отображение текста в Swiftui работает нормально.
Но теперь мне нужно получить доступ к внутренним функциям UITextView из моей модели. Как мне вызвать, например, UITextView.scrollRangeToVisible(_:) или получить доступ к таким свойствам, как UITextView.IsEditable?
Моя модель должна выполнять эти изменения на основе внутренних состояний модели.
Есть идеи? Спасибо
(ps Я знаю о TextEditor в SwiftUI, но мне нужна поддержка iOS 13!)
struct TextView: UIViewRepresentable {
@ObservedObject var config: ConfigModel = .shared
@Binding var text: String
@State var isEditable: Bool
var borderColor: UIColor
var borderWidth: CGFloat
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let myTextView = UITextView()
myTextView.delegate = context.coordinator
myTextView.isScrollEnabled = true
myTextView.isEditable = isEditable
myTextView.isUserInteractionEnabled = true
myTextView.layer.borderColor = borderColor.cgColor
myTextView.layer.borderWidth = borderWidth
myTextView.layer.cornerRadius = 8
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.font = uiView.font?.withSize(CGFloat(config.textsize))
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 {
return true
}
func textViewDidChange(_ textView: UITextView) {
self.parent.text = textView.text
}
}
}
Комментарии:
1. Я знаю этот пост, но моя проблема, как получить доступ к функциям UIKit во время выполнения, там не рассматривается.
Ответ №1:
Вы можете использовать что-то вроде configurator
шаблона обратного вызова, например
struct TextView: UIViewRepresentable {
@ObservedObject var config: ConfigModel = .shared
@Binding var text: String
@State var isEditable: Bool
var borderColor: UIColor
var borderWidth: CGFloat
var configurator: ((UITextView) -> ())? // << here !!
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let myTextView = UITextView()
myTextView.delegate = context.coordinator
myTextView.isScrollEnabled = true
myTextView.isEditable = isEditable
myTextView.isUserInteractionEnabled = true
myTextView.layer.borderColor = borderColor.cgColor
myTextView.layer.borderWidth = borderWidth
myTextView.layer.cornerRadius = 8
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.font = uiView.font?.withSize(CGFloat(config.textsize))
uiView.text = text
// alternat is to call this function in makeUIView, which is called once,
// and the store externally to send methods directly.
configurator?(myTextView) // << here !!
}
// ... other code
}
и используйте его в своем представлении SwiftUI, например
TextView(...) { uiText in
uiText.isEditing = some
}
Примечание: в зависимости от ваших сценариев могут потребоваться дополнительные условия, чтобы избежать циклического обновления, не уверен.