Аксессуар панели инструментов, добавленный в UITextView в качестве UIViewRepresentable, отображается только после первого запуска приложения расширения iMessage

#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 (я ненавижу говорить это, не зная наверняка).