MessageKitを用いてチャットアプリを作ろうと考えています。
こちらを参考にCloud FireStoreを用いながらデータのやり取りができるように進めています。
func updateViewWhenMessageAdded()のところで「unexpectedly found nil while unwrapping an optional value」エラーが出てしまいます。
ここをコメントアウトした時にInputBarに入力したテキストがFirebaseに送られることは確認できたのですが、取り出すことができずチャットのメッセージを見ることができない状態です。
解決の糸口になるページ等ご存知の方がいらっしゃいましたらご教授頂けると幸いです。
Swift
1class ViewController: MessagesViewController { 2 3 private var ref: Firestore! //Cloud Firestoreの情報を参照 4 private var user: User! //ユーザ情報 5 private var handle: DatabaseHandle! //オブザーバーの破棄を適切にする処理 6 var messageList: [Message] = [] //Message型のオブジェクトの入る配列 7 var sendData: [String: Any] = [:] //Cloud Firestoreに書き込む内容を格納する辞書 8 var readData: [[String: Any]] = [] //Cloud Firestoreからの読み込み 9 var deleteData: [[String: Any]] = [] 10 11 let dateFormatter:DateFormatter = DateFormatter() //日時のフォーマットを管理するもの 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 16 // データベース読み取り 17 self.setupFirebase() 18 19 //データベースを生成して参照情報をインスタンス化 20 ref = Firestore.firestore() //リファレンス(参照)の初期化 21 user = Auth.auth().currentUser //ユーザー認証した現在のユーザーを格納 22 23 24 25 26 //データの扱い 27 messagesCollectionView.messagesDataSource = self as MessagesDataSource 28 //レイアウト 29 messagesCollectionView.messagesLayoutDelegate = self as MessagesLayoutDelegate 30 //ディスプレイ 31 messagesCollectionView.messagesDisplayDelegate = self as MessagesDisplayDelegate 32 //Cellの扱い方 33 messagesCollectionView.messageCellDelegate = self as MessageCellDelegate 34 //文字入力の部分 35 messageInputBar.delegate = self as InputBarAccessoryViewDelegate 36 37 // メッセージ入力が始まった時に一番下までスクロールする 38 scrollsToBottomOnKeyboardBeginsEditing = true // default false 39 // 表示している画面とキーボードの重複を防ぐ 40 maintainPositionOnKeyboardFrameChanged = true // default false 41 42 //DateFormatter()で日付と時刻と地域を指定(今回は日本時間を指定) 43 dateFormatter.dateStyle = .medium 44 dateFormatter.timeStyle = .short 45 dateFormatter.locale = Locale(identifier: "ja_JP") 46 47 } 48 49 50 func setupFirebase() { 51 52 // 最新のデータが追加されるたびに最新データを取得する 53 self.updateViewWhenMessageAdded() 54 } 55 56 57 //Cloud Firestoreに書き込みをする際の処理 58 func sendMessageToFirebase(text: String){ 59 if !sendData.isEmpty {sendData = [:] } //辞書の初期化(送信データの中身がからじゃなければ空にする) 60 61 62 let sendRef = ref.collection("chats").addDocument(data: ["senderName": user?.displayName,//送信者の名前 63 "senderId": user?.uid, //送信者のID 64 "content": text, //送信内容(今回は文字のみ) 65 66 "createdAt": dateFormatter.string(from: Date()),//送信時刻 67 "messageId": messageList //送信メッセージのID 68 ]) 69 70 } 71 72 73 //データベースから読み込んだデータを配列(readData)に格納するメソッド 74 func snapshotToArray(snapshot: DataSnapshot){ 75 //中身を0にする 76 if !readData.isEmpty {readData = [] } 77 //スナップショットとは、ある時点における特定のデータベース参照にあるデータの全体像を写し取ったもの 78 if snapshot.children.allObjects as? [DataSnapshot] != nil { 79 let snapChildren = snapshot.children.allObjects as? [DataSnapshot] 80 //snapChildrenの中身の数だけsnapChildをとりだす 81 for snapChild in snapChildren! { 82 //要素を追加していく 83 //snapChildのvalueに値があったらreadDataに追加していく 84 if let postDict = snapChild.value as? [String: Any] { 85 self.readData.append(postDict) 86 } 87 } 88 } 89 } 90 91 //メッセージの画面表示に関するメソッド 92 func displayMessageHuman() { 93 //メッセージリストを初期化 94 if !messageList.isEmpty {messageList = []} 95 96 for itemHuman in readData { 97 print("Humanitem: (itemHuman)\n") 98 let message = Message( 99 sender: Sender(id: itemHuman["senderId"] as! String,displayName: itemHuman["senderName"] as! String), 100 messageId: itemHuman["messageId"] as! String, 101 sentDate: self.dateFormatter.date(from: itemHuman["createdAt"] as! String)!, 102 kind: MessageKind.text(itemHuman["content"] as! String) 103 ) 104 messageList.append(message) 105 } 106 } 107 108 //メッセージが追加された際に読み込んで画面を更新するメソッド 109 func updateViewWhenMessageAdded() { 110 ref.collection("chats").addSnapshotListener{(snapShot, error) in 111 if let err = error { 112 print("Error getting documents: (err)") 113 } else { 114 for document in snapShot!.documents { 115 print("(document.documentID) => (document.data())") 116 } 117 } 118// value.documentChanges.forEach { 119// diff in 120// if (diff.type == .added) { 121// print("New city: (diff.document.data())") 122// let snapshotValue = diff.document.data() 123// let text = snapshotValue["text"] as! String 124// let name = snapshotValue["name"] as! String 125// let date = snapshotValue["timestamp"] as! Date 126// self.messageList.append(self.sendMessageToFirebase(text: text, sender: name, name: name, date: date)) 127// } 128// if (diff.type == .modified) { 129// print("Modified city: (diff.document.data())") 130// } 131// if (diff.type == .removed) { 132// print("Removed city: (diff.document.data())") 133// } 134// } 135 } 136 137 messagesCollectionView.reloadData() 138 messagesCollectionView.scrollToBottom() 139 140 self.messageList.reverse() 141 142 } 143 144 override func viewWillAppear(_ animated: Bool) { 145 super.viewWillAppear(animated) 146 self.navigationController?.setNavigationBarHidden(false, animated: false) 147 } 148 149 override func viewDidAppear(_ animated: Bool) { 150 self.becomeFirstResponder() // inputバーを再表示 151 } 152 153 override func didReceiveMemoryWarning() { 154 super.didReceiveMemoryWarning() 155 } 156} 157 158 159 160 161
字数制限のため拡張部分のコードは省いています。
あなたの回答
tips
プレビュー