PushViewController Дважды, когда я дважды щелкаю слишком быстро - PullRequest
0 голосов
/ 15 января 2019

У меня следующий код, когда я звоню, чтобы перевести ViewController в подробный контроллер чата (чат 1-к-1). Однако, если я нажму слишком быстро, контроллер представления будет сдвинут дважды. Я вижу анимацию дважды. Кто-нибудь может указать мне, где ошибка? Код взят из урока Youtube (Firebase Chat) от LBTA.

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let message = messages[indexPath.row]
    guard let chatPartnerId = message.chatPartnerId() else {return}

    let ref = Database.database().reference().child("users").child(chatPartnerId)
    ref.observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dictionary = snapshot.value as? [String: AnyObject] else {
            return
        }
        let user = ChatUser(dictionary: dictionary)
        user.id = chatPartnerId
        self.showChatControllerForUser(user)

    }, withCancel: nil)

}

func showChatControllerForUser(_ user: ChatUser) {
    let chatLogController = ChatLogController(collectionViewLayout: UICollectionViewFlowLayout())
    chatLogController.chatUser = user
    navigationController?.pushViewController(chatLogController, animated: true)
}

Ответы [ 4 ]

0 голосов
/ 15 января 2019

Там нет ошибки в вашем коде, дважды нажмите на ячейку, это просто то, что Свифт не проверяет.

Вы можете попробовать что-то подобное, чтобы избежать такого поведения:


override func viewWillAppear(){
    super.viewWillAppear()

    self.view.isUserInteractionEnabled = true // you need to enable user interaction if user comes back
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    self.view.isUserInteractionEnabled = false // this will prevent further taps

    let message = messages[indexPath.row]
    guard let chatPartnerId = message.chatPartnerId() else {return}

    let ref = Database.database().reference().child("users").child(chatPartnerId)
    ref.observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dictionary = snapshot.value as? [String: AnyObject] else {
            return
        }
        let user = ChatUser(dictionary: dictionary)
        user.id = chatPartnerId
        self.showChatControllerForUser(user)

    }, withCancel: nil)

}

func showChatControllerForUser(_ user: ChatUser) {
    let chatLogController = ChatLogController(collectionViewLayout: UICollectionViewFlowLayout())
    chatLogController.chatUser = user
    navigationController?.pushViewController(chatLogController, animated: true)
}

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

0 голосов
/ 15 января 2019

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

Таким образом, вы можете либо сразу нажать на контроллер представления, а затем запросить данные на контроллере с принудительным просмотром, либо предотвратить «запрос» с помощью переменной, как это сделал @Robert Dresler.

0 голосов
/ 15 января 2019

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

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    // add this:
    tableView.isUserInteractionEnabled = false
    let message = messages[indexPath.row]
    guard let chatPartnerId = message.chatPartnerId() else {return}

    let ref = Database.database().reference().child("users").child(chatPartnerId)
    ref.observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dictionary = snapshot.value as? [String: AnyObject] else {
            return
        }
        let user = ChatUser(dictionary: dictionary)
        user.id = chatPartnerId
        self.showChatControllerForUser(user)

    }, withCancel: nil)

}

func showChatControllerForUser(_ user: ChatUser) {
    let chatLogController = ChatLogController(collectionViewLayout: UICollectionViewFlowLayout())
    chatLogController.chatUser = user
    // edit this:
    navigationController?.pushViewController(chatLogController, animated: true)

    navigationController?.pushViewController(chatLogController, animated: true, completion: {
        self.tableView.isUserInteractionEnabled = true
    })
}

По умолчанию pushViewController(_:animated:) не имеет обработчика завершения, поэтому в качестве обходного пути мы могли бы добавить следующие расширения для его достижения:

extension UINavigationController {
    public func pushViewController(
        _ viewController: UIViewController,
        animated: Bool,
        completion: @escaping () -> Void)
    {
        pushViewController(viewController, animated: animated)

        guard animated, let coordinator = transitionCoordinator else {
            DispatchQueue.main.async { completion() }
            return
        }

        coordinator.animate(alongsideTransition: nil) { _ in completion() }
    }
}

Цитируется по: https://stackoverflow.com/a/33767837/5501940

0 голосов
/ 15 января 2019

Проблема в том, что вы позволяете пользователю нажимать несколько раз, и это приводит к тому, что контроллер представления нажимается несколько раз. Вы должны предотвратить это.

Итак, одним из вариантов является создание одной глобальной переменной isObserving, которая не позволяет наблюдать несколько раз.

var isObserving: Bool = false

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    if !isObserving {
        isObserving = true
        ...
        ref.observeSingleEvent(of: .value, with: { snapshot in
            ...
            self.isObserving = false
            self.showChatControllerForUser(user)
        })
    }
}

Предложения по улучшению UX. Если наблюдение занимает некоторое время, вы должны сообщить пользователю, что есть что-то, что требует времени. Так, например, вы можете запустить и остановить загрузку UIActivityIndicatorView. Также вы можете запретить пользователю выбирать ячейку несколько раз, работая с таблицей isUserInteractionEnabled.

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...