Расширение iMessage аварийно завершает работу при попытке доступа к UITextView в компактном режиме

Ниже приведен весь мой код в приложении iMessage.

class MessagesViewController: MSMessagesAppViewController {

@IBOutlet weak var messageView: UITextView!

fileprivate func setupMessageView() {
    messageView.delegate = self

    messageView.layer.cornerRadius = 10
    messageView.layer.borderColor = UIColor.black.cgColor
    messageView.layer.borderWidth = 5

    messageView.text = "Tap to enter a message"
    messageView.textColor = UIColor(red:0.80, green:0.81, blue:0.82, alpha:1.0)
    messageView.textAlignment = .center

    messageView.font = UIFont.systemFont(ofSize: 20)

    messageView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
}

func initialize() {
    setupMessageView()
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(self.initialize), userInfo: nil, repeats: false)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Conversation Handling

override func willBecomeActive(with conversation: MSConversation) {
    // Called when the extension is about to move from the inactive to active state.
    // This will happen when the extension is about to present UI.

    // Use this method to configure the extension and restore previously stored state.
}

override func didResignActive(with conversation: MSConversation) {
    // Called when the extension is about to move from the active to inactive state.
    // This will happen when the user dissmises the extension, changes to a different
    // conversation or quits Messages.

    // Use this method to release shared resources, save user data, invalidate timers,
    // and store enough state information to restore your extension to its current state
    // in case it is terminated later.
}

override func didReceive(_ message: MSMessage, conversation: MSConversation) {
    // Called when a message arrives that was generated by another instance of this
    // extension on a remote device.

    // Use this method to trigger UI updates in response to the message.
}

override func didStartSending(_ message: MSMessage, conversation: MSConversation) {
    // Called when the user taps the send button.
}

override func didCancelSending(_ message: MSMessage, conversation: MSConversation) {
    // Called when the user deletes the message without sending it.

    // Use this to clean up state related to the deleted message.
}

override func willTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
    // Called before the extension transitions to a new presentation style.

    // Use this method to prepare for the change in presentation style.
}

override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
    // Called after the extension transitions to a new presentation style.

    // Use this method to finalize any behaviors associated with the change in presentation style.
}

}

extension MessagesViewController: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
    if textView == messageView {
        requestPresentationStyle(.expanded)
        if textView.textColor == UIColor(red:0.80, green:0.81, blue:0.82, alpha:1.0) {
            textView.text = nil
            textView.textAlignment = .left
            textView.textColor = UIColor.black
            textView.font = UIFont.systemFont(ofSize: 20)
        }
    }
}

func textViewDidEndEditing(_ textView: UITextView) {
    if textView == messageView {
        if textView.text.isEmpty {
            textView.text = "Tap to enter a message"
            textView.textAlignment = .center
            textView.textColor = UIColor(red:0.80, green:0.81, blue:0.82, alpha:1.0)
            textView.font = UIFont.systemFont(ofSize: 20)
        }
    }
}
}

У него есть UITextView, и я пытаюсь ввести данные. У меня возникла странная проблема при выполнении этого действия.

При начальной загрузке, если я нажимаю UITextView, вызывается расширенный режим, но клавиатура не сдвигается вверх. Требуется еще одно нажатие, чтобы клавиатура сдвинулась вверх.

В логах мне удалось обнаружить, что методы textViewDidBeginEditing и textViewDidEndEditing вызываются последовательно при первом тапе. Непонятно, почему так происходит!?

В любом случае, что меня больше интригует, так это то, что происходит сейчас. Я могу изменить режим на компактный вручную и обратно на расширенный. В расширенном режиме, когда я нажимаю, клавиатура сдвигается вверх. Но если я нажму в компактном режиме, приложение вылетит!!

И это происходит постоянно. На симуляторе и реальном устройстве. Я понятия не имею, как объяснить это поведение.

Независимо от того, сколько раз я меняю режим с компактного на расширенный и обратно, я могу вводить текст в расширенном режиме. Но, после первого нажатия, это больше не повторяется, пока в компактном режиме.

У кого-нибудь есть эта проблема? Или вы можете повторить это? Это баг Apple?


person Shyam    schedule 13.06.2017    source источник
comment
Это похоже на проблему, с которой я столкнулся, когда я вызывал becomeFirstResponder в том же методе, который вызывал requestPresentationStyle. Смешивание их напрашивается на неприятности. Это может помочь, если вы убедитесь, что текстовое поле не стало первым ответчиком, пока не завершится переход.   -  person Tom Harrington    schedule 15.06.2017
comment
@ Том Харрингтон, хорошо. Итак, я не использовал becomeFirstResponder явно. Или вы имеете в виду, что использование requestPresentationStyle в textViewDidBeginEditing одинаково? Тогда как мы распознаем, что UITextView постучали?   -  person Shyam    schedule 15.06.2017
comment
@TomHarrington, или как убедиться, что UITextView не станет первым ответчиком, пока переход не будет завершен. didTransition(to presentationStyle: ) кстати не работает. ¯_(ツ)_/¯   -  person Shyam    schedule 15.06.2017
comment
В моем случае мы просто не показывали текстовое представление. В компактном режиме есть кнопка, а текстовое представление видно в расширенном режиме. Вы также можете сделать это, отключив редактирование в компактном режиме, но добавив распознаватель жестов касания, чтобы нажатие на текстовое поле инициировало изменение, но оно не стало первым ответчиком, пока изменение не завершится.   -  person Tom Harrington    schedule 16.06.2017
comment
@ТомХаррингтон, ты. Находятся. Просто. Удивительно. Период.   -  person Shyam    schedule 17.06.2017
comment
@TomHarrington, большое спасибо. Опыт показывает!! ????   -  person Shyam    schedule 17.06.2017
comment
@TomHarrington, я согласился с вашим предложением отключить режим редактирования. Клавиатура по-прежнему не отображается и требует еще одного нажатия. Но, я думаю, это на Apple. Собственно, весь вопрос в них.   -  person Shyam    schedule 17.06.2017


Ответы (1)


Если вам нужно изменить стиль представления после того, как пользователь коснется текстового поля, вы можете добавить задержку, чтобы гарантировать отсутствие конфликтов с переходами.

Возможно, лучше изначально запретить отображение клавиатуры (вам может потребоваться установить флаг bool в вашем VC, чтобы отключить его в делегатах textview, чтобы включить это), вызовите

  func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
    if  !shouldShowKeyBoard {
        self.requestPresentationStyle(.expanded)
        return false
    }
    return true

Затем в делегате MSMessagesAppViewController включите клавиатуру, чтобы она стала первым ответчиком `

 override func didTransition(to presentationStyle: MSMessagesAppPresentationStyle) {
    if presentationStyle == .expanded {
       shouldShowKeyBoard = true
       textView.becomeFirstResponder()
    }
}

`

Надеюсь, это поможет

person user499846    schedule 29.04.2020