Search code examples
swiftmodal-dialogseguedismiss

How to dismiss modal and simultaneously send data and perform segue


I have a chat app and want to go from my ChatController to a newMessageVC by using a modal segue. In newMessageVC I got all my contacts shown in a table view. When clicking on a contact the newMessaenter code heregeVC should dismiss and the clicked contact should be sent to ChatController. In this moment the ChatController should perform a segue to go to the ChatVC to show the new chat with the clicked user. How can I do this?

I tried following code:

The newMessageVC is dismissing and the function showChatVC is called (It shows the print statement) but then there is the Error although the segue does exist. There is a segue from ChatController to ChatVC named showChatVC

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<WeAreFriends.ChatController: 0x7fd760e22e80>) has no segue with identifier 'showChatVC''
class ChatController : UITableViewController {

    //MARK: - Outlets

    @IBOutlet weak var MessageTableView: UITableView!


    //MARK: - Properties

    var messages = [MessageModel]()

    //Mark: - Init View Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()

        configureNavigationBar()
    }


    //MARK: - Navigation Bar

    func configureNavigationBar() {
        navigationItem.title = "Messages"
         navigationController?.navigationBar.barTintColor = Defaults.hexStringToUIColor(hex: "#006D79")
        let textAttributes = [NSAttributedString.Key.foregroundColor: Defaults.hexStringToUIColor(hex: "#FFAA01")]
        navigationController?.navigationBar.titleTextAttributes = textAttributes
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(handleNewMessage))
    }

    @objc func handleNewMessage(){
        performSegue(withIdentifier: "showNewMessage", sender: self)
    }

    //MARK: - Show ChatVC

    func showChatVC(forUser user: UserModel){
        print("Shooow, jihaaaaa")
        let messageController = MessageController()
        messageController.user = user
        performSegue(withIdentifier: "showChatVC", sender: self)

    }

    //MARK: - Prepare for segue

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showNewMessage" {
            let destinationVC = segue.destination as! NewMessageController
            destinationVC.chatController = ChatController()
        }

    }

    //MARK: - Table Config

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return messages.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MessagesTableViewCell", for: indexPath) as! MessagesTableViewCell

        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("did select row")
    }
}

newMessageVC:

class NewMessageController: UITableViewController {

    //MARK: - Outlets

    @IBOutlet var NewMessageTableView: UITableView!

    //MARK: - Var/let

    var users = [UserModel]()

    var chatController : ChatController?

    //Mark: - Init View Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()

        configureNavigationBar()
        fetchUser()
    }

    //MARK: - User laden

    func fetchUser(){
        UserApi.shared.observeUsersButCurrentUser { (user) in
            self.users.append(user)
            self.NewMessageTableView.reloadData()
        }
    }

    //MARK: - Navigation Bar

    func configureNavigationBar() {
        navigationItem.title = "New Message"
        navigationController?.navigationBar.barTintColor = Defaults.hexStringToUIColor(hex: "#006D79")
        let textAttributes = [NSAttributedString.Key.foregroundColor: Defaults.hexStringToUIColor(hex: "#FFAA01")]
        navigationController?.navigationBar.titleTextAttributes = textAttributes
    }

    //MARK: - Tableview Config
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return users.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "NewMessageTableViewCell", for: indexPath) as! NewMessageTableViewCell

        cell.user = users[indexPath.row]

        return cell
    }

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

        self.dismiss(animated: true) {

            let user = self.users[indexPath.row]
            self.chatController!.showChatController(forUser: user)
        }
    }

}

What am I doing wrong?


Solution

  • Replace

    destinationVC.chatController = ChatController()
    

    with

    destinationVC.chatController = self
    

    As ChatController() is a new different instance with no storyboard layout attached , so no segues hence the crash


    func showChatVC(forUser user: UserModel){ 
        performSegue(withIdentifier: "showChatVC", sender:user) 
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showNewMessage" {
            let destinationVC = segue.destination as! NewMessageController
            destinationVC.chatController = ChatController()
        }
        else if segue.identifier == "showChatVC" {
            let destinationVC = segue.destination as! ChatVC
            destinationVC.user = sender as! UserModel
        }
    }
    

    Also make

    weak var chatController : ChatController?
    

    As not to cause retain cycles