Search code examples
swiftfirebaseuinavigationcontrolleruinavigationbarjsqmessagesviewcontroller

Navigation Bar is Hidden in JSQMessagesViewController


I am working on incorporating a chat feature in my app and everything is working smoothly using JSQMessagesViewController except that I can't get the navigation bar to show in the view controller. I have tried almost everything it seems like but it seems to be hidden by the view or something although I am not sure of this. Here is my code for the Conversation view controller:

import UIKit
import JSQMessagesViewController
import Firebase
import AVKit

class ConvoVC: JSQMessagesViewController {

var chatRoomId = Variables.chatRoomID
var outgoingBubbleImageView: JSQMessagesBubbleImage!
var incomingBubbleImageView: JSQMessagesBubbleImage!
var messages = [JSQMessage]()

override func viewDidLoad() {
    super.viewDidLoad()

    senderId = uid!
    senderDisplayName = uid!

    let factory = JSQMessagesBubbleImageFactory()

    incomingBubbleImageView = factory?.incomingMessagesBubbleImage(with: UIColor.jsq_messageBubbleLightGray())
    outgoingBubbleImageView = factory?.outgoingMessagesBubbleImage(with: UIColor.jsq_messageBubbleBlue())

    collectionView.collectionViewLayout.incomingAvatarViewSize = CGSize.zero
    collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSize.zero

    let query =  ref.child("ChatRooms").child(chatRoomId!).child("Messages").queryLimited(toLast: 10)

    query.observe(.childAdded, with: { (snapshot) in
        if snapshot.exists(){
        if  let data        = snapshot.value as? [String: String],
            let id          = data["sender_id"],
            let name        = data["name"],
            let text        = data["text"],
            !text.isEmpty
        {
            if let message = JSQMessage(senderId: id, displayName: name, text: text)
            {
                self.messages.append(message)

                self.finishReceivingMessage()
            }
        }
    }
    })

    //let navigationBar = UINavigationBar(frame: CGRect(0, 0, self.view.frame.size.width, 64)) // Offset by 20 pixels vertically to take the status bar into account

    //navigationBar.backgroundColor = UIColor.white
    //navigationBar.delegate = self as! UINavigationBarDelegate

    // Create a navigation item with a title
    //let navigationItem = UINavigationItem()
    //navigationItem.title = contacts[i].firstName

    // Create right button for navigation item
    setupBackButton()

    // Make the navigation bar a subview of the current view controller
    //self.view.addSubview(navigationBar)

}


override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(true)
    self.navigationController?.isNavigationBarHidden = false
}
func setupBackButton() {
    let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(backButtonTapped))
    navigationItem.leftBarButtonItem = backButton
}
@objc func backButtonTapped() {
    dismiss(animated: true, completion: nil)
}



override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
    let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell

    let message = messages[indexPath.item]

    if message.senderId == senderId {
        cell.textView!.textColor = UIColor.white
    } else {
        cell.textView!.textColor = UIColor.black
    }

    return cell
}

override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageDataForItemAt indexPath: IndexPath!) -> JSQMessageData! {
    return messages[indexPath.item]
}


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return messages.count

}



override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!) {
    let messageRef = ref.child("ChatRooms").child(chatRoomId!).child("Messages").childByAutoId()


    let message = ["sender_id": senderId, "name": senderDisplayName, "text": text]

    messageRef.setValue(message)

    finishSendingMessage()
    JSQSystemSoundPlayer.jsq_playMessageSentSound()
    self.finishSendingMessage()

}

override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAt indexPath: IndexPath!) -> JSQMessageBubbleImageDataSource! {
    let message = messages[indexPath.item]
    if message.senderId == senderId {
        return outgoingBubbleImageView
    }else {
        return incomingBubbleImageView
    }
}




}

Here is the code for the didSelectRow method in the class that comes before the conversation view controller:

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

    let chatFunctions = ChatFunctions()

    ref.child("users").child(uid!).observeSingleEvent(of: .value) { (snapshot) in
        let userOne = User(snapshot: snapshot)
        self.chatRoomIdentity = chatFunctions.startChat(user1: userOne , user2: self.matches[indexPath.row])
        self.senderDisName = self.matches[indexPath.row].firstName
        Variables.chatRoomID = self.chatRoomIdentity

        self.present(ConvoVC(), animated: true, completion: nil)

    }




}

Thanks in advance!


Solution

  • You are presenting it modally on this line which would present it full screen (so no navigation bar):

    self.present(ConvoVC(), animated: true, completion: nil)
    

    Push it onto the navigation stack instead like this:

    self.navigationController?.pushViewController(ConvoVC(), animated: true)
    

    If you don't have your first controller set as the root view controller of a navigation controller, make sure to do so beforehand.

    Either that or set ConvoVC as a root view controller of a navigation controller and present that navigation controller

    self.present(navigationController, animated: true, completion: nil).
    

    The first solution will let you pop the ConvoVC and back to the previous view controller via the navigation bar, whereas the latter will not (you would have to dismiss it).

    I highly recommend reading up on iOS navigation & segues as it's a core aspect of any iOS application.