質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • Swift

    7047questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

JSQMessagesでメッセージの送信時間を表示するためのxib変更をしたが、エラーは発生しないがアプリ上に描画されない

受付中

回答 0

投稿

  • 評価
  • クリップ 0
  • VIEW 302

yukky05

score 3

プログラミング初心者です。
JSQMessagesというチャットライブラリを使用しています。

チャット自体は通常通り表示されるのですが、
送信時間を表示するための変更が反映されておらず原因がわからないため、どなたかご教示いただけると幸いです。
*formatter.string(from: message.date)に、stringの値が入っていることは確認済みです。

【やりたいこと】
チャット内のメッセージ横に送信時間を表示させたい

【やったこと】
1)ChatViewControllerクラスで利用しているJSQMessagesのライブラリに入っているxibファイルをコピーし、CustomMessagesCollectionViewCellOutgoing.xibを作成

2)CustomMessagesCollectionViewCellOutgoingクラスを作成

3)UILabelをCustomMessagesCollectionViewCellOutgoing.xibファイル内に追加し、CustomMessagesCollectionViewCellOutgoingクラスに関連づけ

4)ChatViewControllerクラス内にxibをレジスター、タイムラベルを表示するためのコードを記述

[ChatViewControllerクラス]

import UIKit
import Firebase
import JSQMessagesViewController

class ChatViewController: JSQMessagesViewController {

    var sendText:String = ""  //チャット相手のuidが入ってくる
    var senderName:String = "" //チャット相手の名前が入ってくる
    var recieverId:String!
    var userId : String!
    var nickName : String!
    var titleName : String!
    var roomKey : String!
    var messages = [JSQMessage]()
    var item = [NSDictionary]()

    override func viewDidLoad() {
        super.viewDidLoad()
        let outgoingNib = UINib(nibName: "CustomMessagesCollectionViewCellOutgoing", bundle: nil)
        self.collectionView!.register(outgoingNib, forCellWithReuseIdentifier: "customMessagesOutgoing")

        let incomingNib = UINib(nibName: "CustomeMessageCollectionViewCellIncoming", bundle: nil)
        self.collectionView!.register(incomingNib, forCellWithReuseIdentifier: "customMessagesIncoming")


        recieverId = sendText
        let ref = Database.database().reference()

        userId = Auth.auth().currentUser?.uid
        self.senderDisplayName = ""
        senderId = userId

        //既に相手のチャットが存在する場合はそのidを使う
        ref.child("chat").child(userId!).child(recieverId!).observeSingleEvent(of: .value, with: { (snap) in

            if snap.exists() {

                let value = snap.value as? NSDictionary
                self.roomKey = value?["roomkey"] as? String ?? ""

            }else{

                self.roomKey = ref.child("chat").child(self.userId!).child(self.recieverId!).childByAutoId().key

                //チャットがない場合、各ユーザーにチャットのroomKeyを登録する
                let room_information = [ "date": [".sv": "timestamp"],"roomkey":self.roomKey, "members":[self.userId!,self.recieverId!] ] as [String : Any]

                let childUpdates = [
                    "/chat/\(self.userId!)/\(self.recieverId!)/": room_information,
                    "/chat/\(self.recieverId!)/\(self.userId!)/": room_information
                ]
                ref.updateChildValues(childUpdates)
            }

            //messageを取得
            ref.child("chat-message").child(self.roomKey!).observe(.value, with: { snap in

                guard let posts = dic["messages"] as? Dictionary<String, Dictionary<String, AnyObject>> else {
                    return
                }
                // keyとdateが入ったタプルを作る
                var keyValueArray: [(String, Int)] = []
                for (key, value) in posts {
                    keyValueArray.append((key: key, date: value["date"] as? Int ?? 0))
                }
                keyValueArray.sort{$0.1 < $1.1}    // タプルの中のdate でソートしてタプルの順番を揃える(配列で) これでkeyが順番通りになる
                // messagesを再構成
                var preMessages = [JSQMessage]()
                for sortedTuple in keyValueArray {
                    for (key, value) in posts {
                        if key == sortedTuple.0 {           // 揃えた順番通りにメッセージを作成
                            let senderId = value["senderId"] as! String!
                            let text = value["text"] as! String!
                            let displayName = value["displayName"] as! String!
                            preMessages.append(JSQMessage(senderId: senderId, displayName: displayName, text: text))
                        }
                    }
                }
                self.messages = preMessages
                self.collectionView.reloadData()
                self.hideIndicator()
            })

        }) { (error) in


        }
        automaticallyScrollsToMostRecentMessage = true
    }


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



        //吹き出しの横にtimeLabelを追加
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm"
        let message = self.messages[indexPath.item]
        if message.senderId == self.senderId {
            //let cel = super.collectionView(collectionView, cellForItemAt: indexPath) as! CustomMessagesCollectionViewCellOutgoing
            let cel = collectionView.dequeueReusableCell(withReuseIdentifier: "customMessagesOutgoing", for: indexPath) as! CustomMessagesCollectionViewCellOutgoing

            cel.timeLabel.text = formatter.string(from: message.date)

        } else {
            //let cel = super.collectionView(collectionView, cellForItemAt: indexPath) as! CustomeMessageCollectionViewCellIncoming
            let cel = collectionView.dequeueReusableCell(withReuseIdentifier: "customMessagesIncoming", for: indexPath) as! CustomeMessageCollectionViewCellIncoming

            cel.timeLabel.text = formatter.string(from: message.date)
        }
            return cell
    }


    override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!) {

        inputToolbar.contentView.textView.text = ""

        //キーボードを閉じる
        self.view.endEditing(true)

        let ref = Database.database().reference()
        let key = ref.child("chat-message").child(self.roomKey).childByAutoId().key
        let post = ["senderId": self.userId,
                    "displayName": nickName,
                    "text": text,
                    "date": [".sv": "timestamp"]
            ] as [String : Any]

        let childUpdates = ["/chat-message/\(roomKey!)/messages/\(key)/": post]
        ref.updateChildValues(childUpdates)

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

[CustomMessagesCollectionViewCellOutgoingクラス]

import JSQMessagesViewController
import UIKit

class CustomMessagesCollectionViewCellOutgoing: JSQMessagesCollectionViewCellOutgoing {

    @IBOutlet weak var timeLabel: UILabel!

}

[CustomMessagesCollectionViewCellOutgoing.xib]
イメージ説明
イメージ説明

【上記を実行した後のView Hierarchy】
イメージ説明

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    7047questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • トップ
  • Swiftに関する質問
  • JSQMessagesでメッセージの送信時間を表示するためのxib変更をしたが、エラーは発生しないがアプリ上に描画されない