简体   繁体   English

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

[英]NavigationController wont push from function call + swift

I am basically trying to recreate whatsapp. 我基本上试图重新创建whatsapp。 My MainVC has a TableView that shows all current conversations and has a push segue to the ChatVC to display the entire conversation. 我的MainVC有一个TableView,它显示所有当前的对话,并有一个推送到ChatVC的segue以显示整个对话。

When a user wants to start a new conversation they click the button on the top right corner and the UserListVC comes from the bottom and displays a list of users. 当用户想要开始新对话时,他们单击右上角的按钮,UserListVC来自底部并显示用户列表。

My thinking here is that when a user clicks a user the "UsersListVC" dismisses (showing the mainVC) and calls a function to open up the ChatVC. 我的想法是当用户点击用户时“UsersListVC”解散(显示mainVC)并调用一个函数来打开ChatVC。 However I havent been able call a function successfully after this dimiss from MainVC. 但是,在MainVC的这个dimiss之后,我还没能成功调用函数。

在此输入图像描述

Please not right now I am not pushing any data through I just want to get the segues working correctly 请不要现在我没有推送任何数据我只是想让segue正常工作

MainVC.swift MainVC.swift

func showChatVC() {

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

}

UsersListVC.swift UsersListVC.swift

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

I have tried a few different variations and I cant seem to call the function in MainVC at all. 我尝试了一些不同的变化,我似乎无法在MainVC中调用该函数。 Am I being too stubborn with my thinking doing the segues this way? 我是不是太顽固,我的想法是这样做的? Should I have a direct segue from UsersListVC to ChatVC 我应该从UsersListVC直接segue到ChatVC

Try Below Code 尝试以下代码

Step - 1 第1步

  • set up the storyboard identifiers . 设置故事板标识符。

  • then try below code 然后尝试下面的代码

    MainVC.swift MainVC.swift

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

UsersListVC.swift UsersListVC.swift

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

lots of answers here, thought I should add my go to solution for these types of problems, using a delegate pattern. 这里有很多答案,我想我应该使用委托模式为这些类型的问题添加解决方案。

With a delegate you can call a function in MainVC from UsersListVC, this makes it much easier to segue to ChatVC and will also help when you are passing the selected user to ChatVC. 使用委托,您可以从UsersListVC调用MainVC中的函数,这使得更容易转到ChatVC,并且在将所选用户传递给ChatVC时也会有所帮助。

To make a delegate pattern you: 要创建委托模式,您:

  1. create a protocol which specifies the function your delegate class must implement, typically I do this above the delegate class, so MainVC. 创建一个协议,指定你的委托类必须实现的功能,通常我在委托类上面这样做,所以MainVC。

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

  1. have your delegate class (MainVC) conform to the protocol and implement the required function 让您的委托类(MainVC)符合协议并实现所需的功能

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

  1. create a variable in UsersListVC to hold the delegate class in 在UsersListVC中创建一个变量来保存委托类

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

  1. when you present UsersList from MainVC set the delegate variable to MainVC (self), for example if you segue to UsersList then this can be done in prepare for segue. 当您从MainVC呈现UsersList时,将委托变量设置为MainVC(self),例如,如果您转到UsersList,则可以在准备segue时完成此操作。

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

    or if you present it without a segue: 或者如果你提出它没有segue:

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

Your delegate pattern is finished now. 您的委托模式现已完成。 To call the delegate function when you want to create the new conversation and dismiss UserListsVC, you do it like this 要在创建新会话并关闭UserListsVC时调用委托功能,可以这样做

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

        delegate.newConversationCreated(withUser: /*Your User Object*/)

    }

And in MainVC you can implement the newConversationCreated function to: 在MainVC中,您可以将newConversationCreated函数实现为:

  • Dismiss UserLists 关闭用户列表
  • Create ChatVC 创建ChatVC
  • Pass on the user to ChatVC 将用户传递给ChatVC
  • Present ChatVC 目前ChatVC

eg 例如

    func newConversationCreated(withUser user: AnyObject) {

        dismiss(animated: true) { 

            let showChat = ChatVC()
            showChat.user = user
            navigationController?.pushViewController(showChat, animated: false)

        }

    }

ps It may seem weird to call dismiss from MainVC, but this is actually best practice according to apple (see the answer in this question for why). ps从MainVC调用dismiss可能看起来很奇怪,但这实际上是根据apple的最佳实践(请参阅此问题中的答案为什么)。 It will dismiss UserLists don't worry. 它会解雇UserLists不用担心。

Try to send action from your tableView's didSelectRow method like 尝试从tableView's didSelectRow方法发送动作,如

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

Hope this helps. 希望这可以帮助。

I would recommend using the NotificationCenter : 我建议使用NotificationCenter

In MainVC register for NewChatCreateNotification like: MainVC注册NewChatCreateNotification如:

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

Still in MainVC , in the autoNavigateToNewChat: method, push ChatVC 仍然在MainVC ,在autoNavigateToNewChat:方法中,推送ChatVC

Then post your notification after you dismiss UsersListVC 然后在您关闭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])
    }
}

The following should work with your storyboard setup. 以下内容适用于您的故事板设置。 Make sure to set the segue identifiers in the storyboard. 确保在故事板中设置segue标识符。 I am using a button instead of table view cell in the UsersListVC . 我在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?()
        }
    }
}

If I'm not mistaken, you create a new instance of MainVC in your dismiss closure. 如果我没弄错的话,你在解雇闭包中创建一个新的MainVC实例。

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

Since this new ViewController is never shown on screen, it also cannot show another ViewController. 由于这个新的ViewController从未在屏幕上显示,因此它也无法显示另一个ViewController。

Try getting a reference to your existing MainVC . 尝试获取对现有MainVC的引用。

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

Otherwise try using the Notification approach. 否则,请尝试使用通知方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 iOS Swift 4-如何在NavigationController中推送UISearchController - iOS Swift 4 - How to push UISearchController in a NavigationController SideMenu 警告:尝试在 swift 中从它的 navigationController == nil 的位置推送一个视图控制器 - SideMenu Warning: attempt to push a View Controller from where its navigationController == nil in swift 在SWIFT 2.x中以NavigationController编程方式调用UIViewController - Call a UIViewController with NavigationController programmatically in SWIFT 2.x 从Modal View内部推送到iOS NavigationController - Push to iOS NavigationController from inside Modal View 从侧面菜单中在NavigationController中推送ViewController - Push ViewController in NavigationController from side menu 如何从 NavigationController 中的 SwiftUI 视图推送到 UIViewController - How to push to UIViewController from SwiftUI View that is in NavigationController 如何将值从NavigationController推送到rootViewController? - How to push values to the rootViewController from NavigationController? UIAlertView不会调用函数 - UIAlertView wont call function 从ViewController(故事板)调用NavigationController(xib) - Call NavigationController (xib) from ViewController (storyboard) 从js调用swift函数 - Call swift function from js
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM