NavigationController不会从函数调用+ swift推送

时间:2016-10-12 02:27:26

标签: ios swift uinavigationcontroller

我基本上试图重新创建whatsapp。我的MainVC有一个TableView,它显示所有当前的对话,并且有一个推送到ChatVC的segue以显示整个对话。

当用户想要开始新对话时,他们点击右上角的按钮,UserListVC来自底部并显示用户列表。

我的想法是,当用户点击用户时," UsersListVC"解散(显示mainVC)并调用一个函数来打开ChatVC。但是,在MainVC的这个dimiss之后,我还没能成功调用函数。

enter image description here

请不要现在我没有推送任何数据我只想让segue正常工作

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()
            }
        }

我尝试了一些不同的变化,我似乎无法在MainVC中调用该函数。我是不是太顽固,我的想法是这样做的?我应该从UsersListVC直接segue到ChatVC

6 个答案:

答案 0 :(得分:1)

尝试以下代码

  

步骤1

  • 设置故事板标识符。

  • 然后尝试以下代码

    <强> 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()
         }
}

答案 1 :(得分:1)

这里有很多答案,我想我应该使用委托模式为这些类型的问题添加解决方案。

使用委托,您可以从UsersListVC调用MainVC中的函数,这样可以更容易地切换到ChatVC,并且在将所选用户传递给ChatVC时也会有所帮助。

制作委托模式:

  1. 创建一个协议,指定你的委托类必须实现的功能,通常我在委托类上面这样做,所以MainVC。

    protocol UsersListDelegate: class {
    
        func newConversationCreated(withUser user: AnyObject)
    
    }
    
    1. 让您的委托类(MainVC)符合协议并实现所需的功能

      class MainVC: UIViewController, UsersListDelegate {
      
          func newConversationCreated(withUser user: AnyObject) {
      
              //I'll fill this in later in my answer
      
          }
      
      }
      
      1. 在UsersListVC中创建一个变量来保存

        中的委托类
        class UsersListVC: UIViewController {
        
            weak var delegate: UsersListDelegate!
        
        }
        
        1. 当您从MainVC呈现UsersList时,将委托变量设置为MainVC(self),例如,如果您转到UsersList,则可以在准备segue时完成此操作。

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

          或者如果你没有segue提出它:

          func presentUsersList() {
          
              let userListsVC = UsersListVC()
              userListsVC.delegate = self
              self.present(userListsVC, animated: true)
          
          }
          
        2. 您的委托模式现已完成。要在创建新会话并关闭UserListsVC时调用委托功能,您可以这样做

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

          在MainVC中,您可以将newConversationCreated函数实现为:

          • 关闭用户列表
          • 创建ChatVC
          • 将用户传递给ChatVC
          • 目前ChatVC

          e.g。

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

          P.S。从MainVC调用dismiss可能看起来很奇怪,但这实际上是根据apple的最佳实践(参见question中的答案为什么)。它会解雇用户列表,不用担心。

答案 2 :(得分:0)

尝试从您的tableView's didSelectRow方法发送操作,例如

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

希望这会有所帮助。

答案 3 :(得分:0)

我建议使用NotificationCenter

MainVC注册NewChatCreateNotification,例如:

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

仍在MainVC,在autoNavigateToNewChat:方法中,推ChatVC

然后在您解除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])
    }
}

答案 4 :(得分:0)

以下内容适用于您的故事板设置。确保在故事板中设置segue标识符。我在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?()
        }
    }
}

答案 5 :(得分:0)

如果我没有弄错,你可以在解雇关闭中创建一个MainVC的新实例。

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

由于这个新的ViewController从未在屏幕上显示,因此它也无法显示另一个ViewController。

尝试获取对现有MainVC的引用。

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

否则请尝试使用通知方法。