Ограничения, не работающие с навигационным контроллером

Я постараюсь быть настолько быстрым, насколько смогу. У меня есть основное представление с контейнером высотой 0, и всякий раз, когда клавиатура включена, я устанавливаю контейнер на ту же высоту, что и клавиатура, и у меня есть кнопка и поле электронной почты, и я установил ограничения для этого контейнера, в основном подталкивание элементов вверх. Я настроил клавиатуру на включение при загрузке представления, и она нормально работает с основным видом, но как только я нажимаю кнопку для перехода к следующему представлению, клавиатура открывается, но кнопки и поле электронной почты остаются за клавиатурой. потому что ограничения не работают, но когда я нажимаю кнопку «Домой», закрываю приложение (не из фона) и снова открываю его, ограничения работают нормально. Это происходит только тогда, когда я встраиваю навигационный контроллер в основной вид, в противном случае он отлично работает. Любые идеи?

У меня один и тот же код в обоих представлениях. P.S. Извините за длинное сообщение, не знал как объяснить.

@IBOutlet weak var emailTF: UITextField!

@IBOutlet weak var bottomHeight: NSLayoutConstraint!`

override func viewWillAppear(_ animated: Bool)
{
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(
        self,
        selector: #selector(keyboardWillShow),
        name: NSNotification.Name.UIKeyboardWillShow,
        object: nil
    )

    // Show keyboard by default
    emailTF.becomeFirstResponder()
}

@objc func keyboardWillShow(_ notification: Notification)
{
       if let userInfo = notification.userInfo
    {
        if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
            bottomHeight.constant = keyboardSize.height
            view.setNeedsLayout()
        }
    }
}

Обновление: я нашел часть проблемы. При загрузке второго представления мне не удалось получить высоту клавиатуры, я изменил код второго представления с «viewWillAppear» на «viewDidAppear», сделав контейнер таким же, как высота клавиатуры, НО есть еще одна проблема. Когда я загружаю первый вид, я получаю высоту клавиатуры 271 (что правильно), когда я перехожу ко второму виду, высота клавиатуры по какой-то причине составляет 226, заставляя текстовое поле перемещаться на 45. То же самое происходит, когда я нажимаю кнопку Кнопка «Назад», чтобы вернуться от второго представления к первому, высота клавиатуры — 226. Когда я нажимаю кнопку «Домой» и снова открываю приложение, не имеет значения, на каком экране я нахожусь, я получаю высоту клавиатуры 271, что является правильной высотой. . Что я делаю неправильно?

Обновление 2: РЕШЕНО!

Поскольку мой код работал только без навигационного контроллера, у меня было ощущение, что это что-то с быстрой анимацией и переходом, которые имел навигационный контроллер, и это мешало чтению кода перед загрузкой, поэтому я попытался написать эту строку кода emailTF.resignFirstResponder() к моему действию кнопки, и это сработало! Так что в основном мне приходилось убирать клавиатуру, прежде чем загружать ее в следующем представлении. Надеюсь, я помог некоторым пользователям, у которых возникла такая же проблема.


person Alexandre D'Acol    schedule 02.12.2017    source источник


Ответы (2)


сначала убедитесь, что VC, содержащий изменяемое представление, является делегатом текстового поля/текстового представления, а затем вызовите .becomeFirstResponder() из viewWillAppear. Убедитесь, что вы правильно регистрируете/отменяете регистрацию уведомлений клавиатуры. Если это вообще возможно, вы можете использовать представление прокрутки (поверх UIView по умолчанию), чтобы содержать подпредставления ViewControllers вместо изменения ограничений.

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(forName: Notification.Name.UIKeyboardWillShow, object: nil, queue: nil, using: keyboardWasShown)
    NotificationCenter.default.addObserver(forName: Notification.Name.UIKeyboardWillHide, object: nil, queue: nil, using: keyboardWillBeHidden)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillHide, object: nil)
}

func keyboardWasShown(notification: Notification) -> Void {
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    var keyboardSize:CGRect = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    if keyboardSize.size.height <= 0 { // to fix bug on iOS 11
        keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    }
    self.scrollView.contentInset.bottom = keyboardSize.height //add this much
    self.scrollView.scrollIndicatorInsets.bottom = keyboardSize.height //scroll too it.

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize.height
    if let activeField = self.activeTextView {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

func keyboardWillBeHidden(notification: Notification){
    self.scrollView.contentInset.bottom = 0
    self.scrollView.isScrollEnabled = true
    self.scrollView.alwaysBounceVertical = true
}
person RLoniello    schedule 02.12.2017
comment
Я уже нашел проблему и обновил пост. Вы упомянули scrollView, но в моем случае это сработало, потому что я хотел переместиться вверх только на один элемент, а использование scrollView усложнило бы ситуацию. Спасибо за попытку помочь! - person Alexandre D'Acol; 03.12.2017
comment
@AlexandreD'Acol Мне всегда казалось, что проще заменить представление представлением прокрутки и добавить код многократного использования выше. Приятно слышать, что вы исправили это! берегите себя и удачи вашему проекту! - person RLoniello; 04.12.2017
comment
Приятно знать об этом, я никогда не использовал этот метод, но я обязательно попробую. Спасибо ! - person Alexandre D'Acol; 04.12.2017

Используйте эту строку кода self.view.layoutIfNeeded() вместо view.setNeedsLayout()

И убедитесь, что высота клавиатуры у вас правильная или нет.

Спасибо!

person nitin.agam    schedule 02.12.2017
comment
Спасибо, но это не работает, я изменил строку кода и ничего. Также высота клавиатуры правильная, потому что когда я удаляю навигационный контроллер из представлений, он работает хорошо. Также, когда я удаляю навигационный контроллер и снимаю флажок «анимировать» в переходе, он тоже не работает. Похоже, что-то мешает загрузке ограничений, и когда есть какая-то анимация, это позволяет ограничениям работать правильно. - person Alexandre D'Acol; 02.12.2017
comment
Я сделал это просто для проверки, как я уже говорил, код не работает с навигационным контроллером. - person Alexandre D'Acol; 02.12.2017
comment
Единственное, чего я не понимаю, так это то, как он отлично работает без навигационного контроллера? Это странно. - person Alexandre D'Acol; 02.12.2017
comment
Не могли бы вы поделиться полным кодом? Так что я могу запустить и исправить это. - person nitin.agam; 02.12.2017
comment
Я только что проверил и увидел, что функция @objc func keyboardWillShow(_ notification: Notification) не вызывается во втором представлении, что не позволяет контейнеру иметь ту же высоту, что и клавиатура. Есть предположения ? - person Alexandre D'Acol; 03.12.2017