NavigationController 不会从函数调用 + swift 推送
Posted
技术标签:
【中文标题】NavigationController 不会从函数调用 + swift 推送【英文标题】:NavigationController wont push from function call + swift 【发布时间】:2016-10-12 02:27:25 【问题描述】:我基本上是在尝试重新创建 whatsapp。我的 MainVC 有一个 TableView 可以显示所有当前的对话,并且有一个推送到 ChatVC 以显示整个对话。
当用户想要开始新的对话时,他们点击右上角的按钮,UserListVC 从底部出现并显示用户列表。
我的想法是,当用户单击用户时,“UsersListVC”会关闭(显示 mainVC)并调用一个函数来打开 ChatVC。但是,在 MainVC 关闭后,我无法成功调用函数。
请不要现在我没有推送任何数据我只是想让segues正常工作
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 中调用该函数。我是不是太固执地想以这种方式做segues?我应该直接从 UsersListVC 转到 ChatVC
【问题讨论】:
什么是dismiss(animated: )
?
在这一行 let showChat = ChatVC(),你正在创建一个新的聊天 VC 实例。相反,您需要访问您在情节提要中创建的“实例”。为此,请给 segue 一个标识符并调用 performSegueWithIdentifier 方法。
我尝试将 performSegue 调用放入我的函数 showChatVC 但当我在 NewMessageVC 中选择一行时,我什至无法调用该函数 showChatVC
或者我是否想到了如何实现这个错误,我应该在选择用户后从我的 NewMessageVC 转到聊天?
MainVC().showChatVC()
创建MainVC
的新实例。这个新实例不在视图层次结构中,也不在导航控制器中。因此调用navigationController?.pushViewController(showChat, animated: false)
什么都不做,因为navigationController
是nil
。您需要检索对现有 MainVC
的引用,而不是创建新的。
【参考方案1】:
这里有很多答案,我想我应该使用委托模式为这些类型的问题添加我的解决方案。
通过委托,您可以从 UsersListVC 中调用 MainVC 中的函数,这使得与 ChatVC 的 segue 变得更加容易,并且在您将选定的用户传递给 ChatVC 时也会有所帮助。
要制作委托模式,您:
创建一个协议来指定您的委托类必须实现的功能,通常我在委托类之上执行此操作,因此 MainVC。
protocol UsersListDelegate: class
func newConversationCreated(withUser user: AnyObject)
让您的委托类 (MainVC) 符合协议并实现所需的功能
class MainVC: UIViewController, UsersListDelegate
func newConversationCreated(withUser user: AnyObject)
//I'll fill this in later in my answer
在 UsersListVC 中创建一个变量来保存委托类
class UsersListVC: UIViewController
weak var delegate: UsersListDelegate!
当您从 MainVC 呈现 UsersList 时,将委托变量设置为 MainVC(self),例如,如果您转到 UsersList,则可以在准备 segue 时完成。
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if let destination = segue.destination as? UsersListVC
destination.delegate = self
或者如果你没有转场就展示它:
func presentUsersList()
let userListsVC = UsersListVC()
userListsVC.delegate = self
self.present(userListsVC, animated: true)
您的委托模式现已完成。要在要创建新对话并关闭 UserListsVC 时调用委托函数,您可以这样做
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
delegate.newConversationCreated(withUser: /*Your User Object*/)
在 MainVC 中,您可以实现 newConversationCreated 函数:
关闭用户列表 创建 ChatVC 将用户传递给 ChatVC 介绍 ChatVC例如
func newConversationCreated(withUser user: AnyObject)
dismiss(animated: true)
let showChat = ChatVC()
showChat.user = user
navigationController?.pushViewController(showChat, animated: false)
附言从 MainVC 调用dismiss 可能看起来很奇怪,但这实际上是苹果的最佳实践(请参阅此question 中的答案以了解原因)。它会关闭用户列表,不用担心。
【讨论】:
【参考方案2】:试试下面的代码
步骤 - 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()
【讨论】:
【参考方案3】:尝试从您的 tableView's didSelectRow
方法发送操作,例如
UIApplication.sharedApplication().sendAction("showChatVC", to: nil, from: nil, forEvent: nil)
希望这会有所帮助。
【讨论】:
【参考方案4】:我建议使用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])
【讨论】:
【参考方案5】:以下内容应该适用于您的故事板设置。确保在情节提要中设置 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?()
【讨论】:
【参考方案6】:如果我没记错的话,您可以在您的关闭闭包中创建一个 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()
否则尝试使用通知方法。
【讨论】:
以上是关于NavigationController 不会从函数调用 + swift 推送的主要内容,如果未能解决你的问题,请参考以下文章
Tab Bar 子 viewWillAppear 不会触发,添加 NavigationController 会给出两个导航栏
如果我在 iOS 8 中更改 topviewcontroller 的方向,则不会调用 NavigationController willRotateToInterfaceOrientation
添加NavigationController不会显示后退按钮
关闭没有 NavigationController 的推送视图控制器