NavigationController no presionará desde la function llamada + swift

Básicamente estoy tratando de recrear whatsapp. My MainVC tiene un TableView que muestra todas las conversaciones actuales y tiene una inserción segura en el ChatVC para mostrar toda la conversación.

Cuando un usuario desea iniciar una nueva conversación, hacen clic en el button en la esquina superior derecha y el UserListVC viene desde la parte inferior y muestra una list de usuarios.

Mi pensamiento aquí es que cuando un usuario hace clic en un usuario, "UsersListVC" descarta (mostrando el mainVC) y llama a una function para abrir el ChatVC. Sin embargo, no he podido llamar a una function con éxito después de esta dimiss de MainVC.

introduzca la descripción de la imagen aquí

Por favor, no ahora No estoy empujando ningún dato a través Solo quiero hacer que los segues funcionen correctamente

MainVC.swift

func showChatVC() { print("FUnction called") let showChat = ChatVC() navigationController?.pushViewController(showChat, animated: false) } 

UsersListVC.swift

  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { dismiss(animated: true) { MainVC().showChatVC() } } 

He intentado algunas variaciones diferentes y no puedo llamar a la function en MainVC en absoluto. ¿Estoy siendo demasiado terco con mi pensamiento haciendo las segues de esta manera? ¿Debo tener una segue directa de UsersListVC a ChatVC?

muchas respuestas aquí, pensé que debería agregar mi solución a este tipo de problemas, usando un patrón de delegado.

Con un delegado puede llamar a una function en MainVC desde UsersListVC, esto hace que sea mucho más fácil seguir a ChatVC y también lo ayudará cuando esté pasando el usuario seleccionado a ChatVC.

Para hacer un patrón de delegado, usted:

  1. cree un protocolo que especifique la function que debe implementar su class de delegado, generalmente lo hago arriba de la class de delegado, por lo que MainVC.

     protocol UsersListDelegate: class { func newConversationCreated(withUser user: AnyObject) } 

  1. haga que su class de delegado (MainVC) se ajuste al protocolo e implemente la function requerida

     class MainVC: UIViewController, UsersListDelegate { func newConversationCreated(withUser user: AnyObject) { //I'll fill this in later in my answer } } 

  1. cree una variable en UsersListVC para mantener la class de delegado en

     class UsersListVC: UIViewController { weak var delegate: UsersListDelegate! } 

  1. cuando presente UsersList de MainVC establezca la variable de delegado en MainVC (self), por ejemplo, si se ajusta a UserList, esto se puede hacer para prepararse para segue.

     override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let destination = segue.destination as? UsersListVC { destination.delegate = self } } 

    o si lo presenta sin una segue:

     func presentUsersList() { let userListsVC = UsersListVC() userListsVC.delegate = self self.present(userListsVC, animated: true) } 

Su patrón de delegado ha terminado ahora. Para llamar a la function de delegado cuando desee crear la nueva conversación y descartar UserListsVC, hágalo de esta manera.

  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { delegate.newConversationCreated(withUser: /*Your User Object*/) } 

Y en MainVC puede implementar la function newConversationCreated para:

  • Descartar lists de usuarios
  • Crear ChatVC
  • Pase al usuario a ChatVC
  • Presente ChatVC

p.ej

  func newConversationCreated(withUser user: AnyObject) { dismiss(animated: true) { let showChat = ChatVC() showChat.user = user navigationController?.pushViewController(showChat, animated: false) } } 

ps Puede parecer extraño llamar a rechazar de MainVC, pero esta es realmente la mejor práctica según Apple (ver la respuesta en esta pregunta para saber por qué). Descartará UserLists no se preocupe.

Prueba debajo del código

Paso 1

  • configurar los identificadores de storyboards.

  • luego intente a continuación el código

    MainVC.swift

      func showChatVC() { let showChat = self.storyboard!.instantiateViewControllerWithIdentifier("ChatVc_ID") as! ChatVC self.navigationController?.pushViewController(showChat, animated: false) } 

UsersListVC.swift

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { dismiss(animated: true) { let mainVC = self.storyboard!.instantiateViewControllerWithIdentifier("MainVC_ID") as! MainVC mainVC.showChatVC() } } 

Trate de enviar acciones desde el método tableView's didSelectRow como

 UIApplication.shanetworkingApplication().sendAction("showChatVC", to: nil, from: nil, forEvent: nil) 

Espero que esto ayude.

Recomendaría usar NotificationCenter :

En MainVC regístrese para NewChatCreateNotification como:

 NotificationCenter.default.addObserver(self, selector: #selector(autoNavigateToNewChat(_:)), name: NSNotification.Name(rawValue: "NewChatCreateNotification"), object: nil) 

Todavía en MainVC , en el método autoNavigateToNewChat: empuje ChatVC

Luego publique su notificación después de que descarte UsersListVC

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { //Use this dict to populate the userInfo of the notification, then you can use it when you push to ChatVC. //You can obviously add more info to it like userId etc. as long as the data conforms to: [AnyHashable: Any] let dict = ["chatId" as NSString : <the selected chatId> as NSNumber] dismiss(animated: true) { NotificationCenter.default.post(name: Notification.Name(rawValue: "NewChatCreatedNotification"), object: self, userInfo: dict as [AnyHashable: Any]) } } 

Lo siguiente debería funcionar con la configuration de su guión gráfico. Asegúrate de configurar los identificadores segue en el guión gráfico. Estoy usando un button en lugar de la celda de vista de tabla en UsersListVC .

 import Foundation import UIKit internal enum SegueIdentifier: String { case showChat = "showChat" case showUserList = "showUserList" } internal final class MainVC: UIViewController { override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == SegueIdentifier.showUserList.rawValue, let vc = segue.destination as? UsersListVC { vc.completion = { [weak self] in self?.performSegue(withIdentifier: SegueIdentifier.showChat.rawValue, sender: nil) } } } } internal final class ChatVC: UIViewController { } internal final class UsersListVC: UIViewController { internal var completion: (() -> ())? = nil @IBAction func close(_ sender: UIButton) { dismiss(animated: true) { [weak self] in self?.completion?() } } } 

Si no me equivoco, cree una nueva instancia de MainVC en su cierre de desestimación.

 dismiss(animated: true) { MainVC().showChatVC() } 

Dado que este nuevo ViewController nunca se muestra en la pantalla, tampoco puede mostrar otro ViewController.

Intente get una reference a su MainVC existente.

 dismiss(animated: true) { [weak self] in if let mainVC = self?.presentingViewController as? MainVC { self?.mainVC.showChatVC() } } 

De lo contrario, intente utilizar el enfoque de notificación.