#swiftui #uitextview #toolbar #imessage-extension #uiviewrepresentable
#swiftui #uitextview #панель инструментов #imessage-расширение #uiviewrepresentable
Вопрос:
Хотелось бы, чтобы панель инструментов отображалась постоянно.
Любая помощь будет очень признательна, так как это очень затрудняет работу пользователя.
Я добавил панель инструментов к клавиатуре для TextView, как показано ниже.
Однако панель инструментов отображается только после однократного запуска приложения. Это означает, что панель инструментов не отображается при первом запуске приложения. приложение работает каждый раз после первоначальной загрузки.
Это на IOS 14.3, Xcode 12.3, Swift 5, приложение расширения iMessage. Сбой на симуляторе или реальном устройстве.
struct CustomTextEditor: UIViewRepresentable {
@Binding var text: String
private var returnType: UIReturnKeyType
private var keyType: UIKeyboardType
private var displayDoneBar: Bool
private var commitHandler: (()->Void)?
init(text: Binding<String>,
returnType: UIReturnKeyType = .done,
keyboardType: UIKeyboardType,
displayDoneBar: Bool,
onCommit: (()->Void)?) {
self._text = text
self.returnType = returnType
self.keyType = keyboardType
self.displayDoneBar = displayDoneBar
self.commitHandler = onCommit
}
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.keyboardType = keyType
textView.returnKeyType = returnType
textView.backgroundColor = .clear
textView.font = UIFont.systemFont(ofSize: 20, weight: .regular)
textView.isEditable = true
textView.delegate = context.coordinator
if self.displayDoneBar {
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace,
target: self,
action: nil)
let doneButton = UIBarButtonItem(title: "Close Keyboard",
style: .done,
target: self,
action: #selector(textView.doneButtonPressed(button:)))
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
toolBar.items = [flexibleSpace, doneButton, flexibleSpace]
toolBar.setItems([flexibleSpace, doneButton, flexibleSpace], animated: true)
toolBar.sizeToFit()
textView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
textView.translatesAutoresizingMaskIntoConstraints = true
textView.inputAccessoryView = toolBar
}
return textView
}
func updateUIView(_ textView: UITextView, context: Context) {
textView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextViewDelegate {
var parent: CustomTextEditor
init(_ textView: CustomTextEditor) {
self.parent = textView
}
func textViewDidChange(_ textView: UITextView) {
self.parent.$text.wrappedValue = textView.text
}
func textViewDidEndEditing(_ textView: UITextView) {
self.parent.$text.wrappedValue = textView.text
parent.commitHandler?()
}
}
}
extension UITextView {
@objc func doneButtonPressed(button:UIBarButtonItem) -> Void {
self.resignFirstResponder()
}
}
Вот как это называется…
import SwiftUI
final class ContentViewHostController: UIHostingController<ContentView> {
weak var myWindow: UIWindow?
init() {
super.init(rootView: ContentView())
}
required init?(coder: NSCoder) {
super.init(coder: coder, rootView: ContentView())
}
}
let kTextColor = Color(hex: "3E484F")
let kOverlayRadius: CGFloat = 10
let kOverlayWidth: CGFloat = 2
let kOverlayColor = kTextColor
struct ContentView: View {
@State var text = ""
var body: some View {
VStack {
Spacer()
CustomTextEditor(text: $text, returnType: .default, keyboardType: .default, displayDoneBar: true, onCommit: nil)
.foregroundColor(kTextColor)
.overlay(
RoundedRectangle(cornerRadius: kOverlayRadius)
.stroke(kOverlayColor, lineWidth: kOverlayWidth)
)
.frame(width: 200, height: 100, alignment: .center)
Spacer()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
From MessagesViewController...
override func willBecomeActive(with conversation: MSConversation) {
let childViewCtrl = ContentViewHostController()
childViewCtrl.view.layoutIfNeeded() // avoids snapshot warning?
if let window = self.view.window {
childViewCtrl.myWindow = window
window.rootViewController = childViewCtrl
}
}
Комментарии:
1. Что вы имеете в виду в первый раз? Если я открываю приложение, оно не вызывает firstResponder. Следовательно, клавиатура не отображается, и поэтому нет панели инструментов. Вы хотите немедленно приступить к редактированию?
2. При первой установке и запуске приложения отображается представление, содержащее текстовое представление. Пользователь нажимает на TextView для добавления данных. Клавиатура НЕ имеет панели инструментов. Закройте приложение, запустите снова (или любой последующий запуск), коснитесь TextView, и панель инструментов появится.
3. Извините, я должен был сказать, что это приложение iMessage. Я только что создал автономное тестовое приложение, отличное от iMessage, которое отлично запускает панель инструментов. Так что, скорее всего, это проблема с iMessage и textview. Я добавил уменьшенную версию.
4. обновление: у меня работает уменьшенная версия. Итак, это означает, что что-то в других частях представления (которое я удалил здесь для краткости и безопасности) вызывает проблему. Если кто-то еще видит это поведение, я был бы признателен, если бы знал, что может вызвать это?
5. Обходной путь: я отключил просмотры приложения iMessage, чтобы иметь только то, что отображается выше. Проблема по-прежнему сохраняется. Похоже, что проблема где-то в MessagesViewController. Обходной путь заключается в том, чтобы предоставить пользователю сообщение об установке приложения (первом запуске) для перезапуска iMessage и с помощью UserDefaults определить, является ли это первым запуском или нет, продолжить работу в приложении или отобразить это сообщение. Мой код не меняется от начального запуска к последующим запускам. Только среда. Похоже, это ошибка в iMessage (я ненавижу говорить это, не зная наверняка).