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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Swift

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

Q&A

解決済

2回答

2036閲覧

Facebookのコメント投稿画面のようにタイムライン画面から遷移後のページでコメント投稿を実装したい

iOS25535009

総合スコア12

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Swift

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

0グッド

1クリップ

投稿2020/01/09 14:27

前提・実現したいこと

Xcode11.3
Swift5
macOSMojave10.14.6

フェイスブックのコメントボタンを押した時のような、TableViewのタイムライン画面から個別の画面に遷移

TextFieldにコメントを入力後、投稿ボタンを押すと、遷移前のタイムライン画面でタップしたセルと同じポストデータにコメント文が追加され、遷移後のページにあるUILabelかUITextViewにコメントが投稿される

別のユーザーがコメント投稿すると下に増えていく

タイムライン画面ではUItableViewを使い、それぞれのセルはxibファイルを使い、データベースはFirebaseを使ってます。
遷移先にはUIView,UIButton,UILabel(UITextView)があります。

発生している問題・エラーメッセージ

上記
「遷移前のタイムライン画面でタップしたセルと同じポストデータにコメント文が追加され、遷移後のページにあるUILabelかUITextViewにコメントが投稿される」
の実装がわからずあれこれやってもindexPath.rowを渡す・受け取るの部分ができません。

該当のソースコード

●タイムライン画面

swift

1import UIKit 2import Firebase 3 4class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 5 6 @IBOutlet weak var tableView: UITableView! 7 8 var postArray: [PostData] = [] 9 10 // DatabaseのobserveEventの登録状態を表す 11 var observing = false 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 16 tableView.delegate = self 17 tableView.dataSource = self 18 19 let nib = UINib(nibName: "PostTableViewCell", bundle: nil) 20 tableView.register(nib, forCellReuseIdentifier: "Cell") 21 22 // テーブル行の高さをAutoLayoutで自動調整する 23 tableView.rowHeight = UITableView.automaticDimension 24 // テーブル行の高さの概算値を設定しておく 25 // 高さ概算値 = 「縦横比1:1のUIImageViewの高さ(=画面幅)」+「いいねボタン、キャプションラベル、その他余白の高さの合計概算(=100pt)」 26 tableView.estimatedRowHeight = UIScreen.main.bounds.width + 100 27 } 28 29 override func viewWillAppear(_ animated: Bool) { 30 super.viewWillAppear(animated) 31 print("DEBUG_PRINT: viewWillAppear") 32 33 if Auth.auth().currentUser != nil { 34 if self.observing == false { 35 // 要素が追加されたらpostArrayに追加してTableViewを再表示する 36 let postsRef = Database.database().reference().child(Const.PostPath) 37 postsRef.observe(.childAdded, with: { snapshot in 38 print("DEBUG_PRINT: .childAddedイベントが発生しました。") 39 40 // PostDataクラスを生成して受け取ったデータを設定する 41 if let uid = Auth.auth().currentUser?.uid { 42 let postData = PostData(snapshot: snapshot, myId: uid) 43 self.postArray.insert(postData, at: 0) 44 45 // TableViewを再表示する 46 self.tableView.reloadData() 47 } 48 }) 49 // 要素が変更されたら該当のデータをpostArrayから一度削除した後に新しいデータを追加してTableViewを再表示する 50 postsRef.observe(.childChanged, with: { snapshot in 51 print("DEBUG_PRINT: .childChangedイベントが発生しました。") 52 53 if let uid = Auth.auth().currentUser?.uid { 54 // PostDataクラスを生成して受け取ったデータを設定する 55 let postData = PostData(snapshot: snapshot, myId: uid) 56 57 // 保持している配列からidが同じものを探す 58 var index: Int = 0 59 for post in self.postArray { 60 if post.id == postData.id { 61 index = self.postArray.firstIndex(of: post)! 62 break 63 } 64 } 65 66 // 差し替えるため一度削除する 67 self.postArray.remove(at: index) 68 69 // 削除したところに更新済みのデータを追加する 70 self.postArray.insert(postData, at: index) 71 72 // TableViewを再表示する 73 self.tableView.reloadData() 74 } 75 }) 76 77 // DatabaseのobserveEventが上記コードにより登録されたため 78 // trueとする 79 observing = true 80 } 81 } else { 82 if observing == true { 83 // ログアウトを検出したら、一旦テーブルをクリアしてオブザーバーを削除する。 84 // テーブルをクリアする 85 postArray = [] 86 tableView.reloadData() 87 // オブザーバーを削除する 88 let postsRef = Database.database().reference().child(Const.PostPath) 89 postsRef.removeAllObservers() 90 91 // DatabaseのobserveEventが上記コードにより解除されたため 92 // falseとする 93 observing = false 94 } 95 } 96 } 97 //セルの数を決めるメソッド 98 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 99 return postArray.count 100 } 101 //セルを構築する際に呼ばれるメソッド 102 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 103 // セルを取得してデータを設定する 104 let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PostTableViewCell 105 cell.setPostData(postArray[indexPath.row]) 106 107 // セル内のボタンのアクションをソースコードで設定する 108 cell.likeButton.addTarget(self, action:#selector(handleButton(_:forEvent:)), for: .touchUpInside) 109 110 return cell 111 } 112 113 //セルをタップしたら...のメソッド 114 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 115 116 // タップされたセルの行番号を出力 117 print("(indexPath.row)番目の行が選択されました。") 118 119 let postData = postArray[indexPath.row] 120 121 //記事画面へ遷移(セグエ) 122 let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "Article") as! ArticleViewController 123 //completionでSetPostDataに渡す 124 self.present(nextVC, animated: true, completion: { 125 nextVC.SetPostData(postData) 126 }) 127 performSegue(withIdentifier: "Article", sender: postArray[indexPath.row]) 128 //セルの選択を解除 129 tableView.deselectRow(at: indexPath, animated: true) 130 131 } 132}

●遷移後のコメント投稿画面

swift

1import UIKit 2import Firebase 3import SVProgressHUD 4 5class ArticleViewController: UIViewController,UITextFieldDelegate { 6 7 @IBOutlet weak var ArticleImage: UIImageView! 8 @IBOutlet weak var ArticleLabel: UILabel! 9 @IBOutlet weak var ArticleButton: UIButton! 10 @IBOutlet weak var ArticleLilkeCount: UILabel! 11 @IBOutlet weak var CommentLabel: UILabel! 12 @IBOutlet weak var CommentTextField: UITextField! 13 //postarrayの配列 14 var postArray: [PostData] = [] 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 self.CommentTextField.delegate = self 19 CommentTextField.returnKeyType = .done 20 } 21 22 func SetPostData(_ postData: PostData) { 23 //イメージ画像 24 self.ArticleImage.image = postData.image 25 //キャプションのテキスト 26 self.ArticleLabel.text = "(postData.name!) : (postData.caption!)" 27 //いいねの数 28 let likeNumber = postData.likes.count 29 ArticleLilkeCount.text = "(likeNumber)" 30 31 //いいねボタン 32 if postData.isLiked { 33 let buttonImage = UIImage(named: "like_exist") 34 self.ArticleButton.setImage(buttonImage, for: .normal) 35 } else { 36 let buttonImage = UIImage(named: "like_none") 37 self.ArticleButton.setImage(buttonImage, for: .normal) 38 } 39 //allCommentは最初は空である 40 var allComment = "" 41 42 //postData.commentsの中から要素をひとつずつ取り出すのを繰り返す、というのがcomment 43 for comment in postData.comments{ 44 //comment + comment = allCommentである 45 allComment += comment 46 //commentLabelに表示するのはallComment(commentを足していったもの)である 47 self.CommentLabel.text = allComment 48 } 49 } 50 51 //キーボードを閉じる 52 @IBAction func textField(_ sender: Any) { 53 CommentTextField.text = (sender as AnyObject).text 54 } 55 //コメント投稿ボタン 56 @IBAction func CommentButton(_ sender: UIButton,_ postData: PostData,indexPath: IndexPath) { 57 58 let indexPath = postArrey[indexPath.row], 59 //現在の使用者の表示名がnilじゃなかったら、displayNameに代入し、 60 if let displayName = Auth.auth().currentUser?.displayName, 61 //cell.textField.textをtextと定義する 62 let commentText = self.CommentTextField.text { 63 64 //であれば、cell(PostTableViewCell)のtextFieldをプリントする 65 print(self.CommentTextField.text as Any) 66 67 //であれば、postData.commentsにtextをappend(追加)する 68 postData.comments.append("(displayName): (commentText)\n") 69 70 } 71 72 // 増えたcommentsをFirebaseに保存する 73 let postRef = Database.database().reference().child(Const.PostPath).child(postData.id!) 74 //comments辞書 75 let commentDictionary = ["comments": postData.comments] 76 //Firebaseに辞書を保存する 77 postRef.updateChildValues(commentDictionary) 78 } 79}

試したこと

遷移前ページのdidSelectRowAt内で

performSegue(withIdentifier: "Article", sender: postArray[indexPath.row]) ```でセルの行番号を送ろうとしていますが、合っているのかがわかりません。 遷移後ページのアクションボタン内で

@IBAction func CommentButton(_ sender: UIButton,_ postData: PostData,indexPath: IndexPath) {

let indexPath = postArrey[indexPath.row], //現在の使用者の表示名がnilじゃなかったら、displayNameに代入し、 if let displayName = Auth.auth().currentUser?.displayName, //cell.textField.textをtextと定義する let commentText = self.CommentTextField.text { //であれば、cell(PostTableViewCell)のtextFieldをプリントする print(self.CommentTextField.text as Any) //であれば、postData.commentsにtextをappend(追加)する postData.comments.append("(displayName): (commentText)\n") }
遷移前でのセル行番号を取得する方法がわかりません。 色々調べてもたどり着けませんでした。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

遷移元のViewContoroller

//セルをタップしたら...のメソッド func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // タップされたセルの行番号を出力 print("(indexPath.row)番目の行が選択されました。") let postData = postArray[indexPath.row] postDataToSend = postData performSegue(withIdentifier: "Article", sender: tableView) //セルの選択を解除 tableView.deselectRow(at: indexPath, animated: true) } var postDataToSend: PostData? override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "Article" { let nextVC = segue.destination as! ArticleViewController if let postData = postDataToSend { nextVC.setPostData(postData) } } }

遷移先のViewController

class ArticleViewController: UIViewController,UITextFieldDelegate { @IBOutlet weak var articleImage: UIImageView! @IBOutlet weak var articleLabel: UILabel! @IBOutlet weak var articleButton: UIButton! @IBOutlet weak var articleLilkeCount: UILabel! @IBOutlet weak var commentTextView: UITextView! @IBOutlet weak var commentTextField: UITextField! //前画面からデータを受け取るための変数 var postDataReceived: PostData? func setPostData(_ postData: PostData) { postDataReceived = postData } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) guard let postData = postDataReceived else { return } //イメージ画像 self.articleImage.image = postData.image //キャプションのテキスト self.articleLabel.text = "(postData.caption!)" //いいねの数 let likeNumber = postData.likes.count articleLilkeCount.text = "(likeNumber)" //いいねボタン if postData.isLiked { let buttonImage = UIImage(named: "like_exist") self.articleButton.setImage(buttonImage, for: .normal) } else { let buttonImage = UIImage(named: "like_none") self.articleButton.setImage(buttonImage, for: .normal) } //allCommentは最初は空である var allComment = "" //postData.commentsの中から要素をひとつずつ取り出すのを繰り返す、というのがcomment for comment in postData.comments{ //comment + comment = allCommentである allComment += comment //commentLabelに表示するのはallComment(commentを足していったもの)である self.commentTextView.text = allComment } //コメント投稿ボタン @IBAction func commentButton(_ sender: UIButton) { // 前画面から受け取ったデータを取り出す guard let postData = postDataReceived else { return } //cell.textField.textがnilじゃなかったら、commentTextとする if let commentText = self.commentTextField.text { //であれば、cell(PostTableViewCell)のtextFieldをプリントする print(self.commentTextField.text as Any) //であれば、postData.commentsにcommentTextをappend(追加)する postData.comments.append("(commentText)\n") } // 増えたcommentsをFirebaseに保存する let postRef = Database.database().reference().child(Const.PostPath).child(postData.id!) //comments辞書 let commentDictionary = ["comments": postData.comments] //Firebaseに辞書を保存する postRef.updateChildValues(commentDictionary) //allCommentは最初は空である var allComment = "" //postData.commentsの中から要素をひとつずつ取り出すのを繰り返す、というのがcomment for comment in postData.comments{ //comment + comment = allCommentである allComment += comment //commentLabelに表示するのはallComment(commentを足していったもの)である self.commentTextView.text = allComment } }

投稿2020/01/13 05:48

iOS25535009

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

コメントボタンは、tableViewcellの中にあるボタンでそれを押し、indexを渡したいといった認識でお間違いなければ、protocolを使ってみてはいかがでしょうか?

【tableViewCell.swift】の一番上 import UIKitの上に

protocol UserTableViewCellDelegate { func didTapCommentButton(indexPath: IndexPath) }

下に

@IBAction func commentButton(){ delegate!.didTapCommentButton(indexPath: indexPath) }

を宣言して、
HomeViewControllerにtableViewCellDelegateを書く

class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate ,tableViewCellDelegate{

HomeViewController内に func didTapCommnetButtonを定義する

func didTapCommentButton(indexPath: IndexPath){ //ここで行いたい処理をかく }

これでcellのボタンからindexPath諸々の情報を紐付けることができると思います
間違っていたらすいません!

投稿2020/01/13 05:21

hotateman0913

総合スコア40

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

iOS25535009

2020/01/13 05:44

わかりやすく丁寧なご説明ありがとうございます。ちょうど解決いたしましたので、大丈夫となりました。せっかくご回答いただいたのに、申し訳ございません。今後の参考にいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問