🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Firebase

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

Swift

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

Q&A

解決済

1回答

647閲覧

Swift タイムライン画面から遷移し、次画面で同じ画像・テキストを表示したい

iOS25535009

総合スコア12

Firebase

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

Swift

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

0グッド

1クリップ

投稿2020/01/05 14:41

編集2020/01/05 15:30

前提・実現したいこと

Xcode11.3
Swift5
macOSMojave10.14.6

フェイスブックのコメントボタンを押した時のような、タイムライン画面から個別の画面に遷移し、タイムラインで表示されていた画像やテキストなどが遷移先でも表示されるようにしたい

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

タップされたCellのindexPathをキーにして、タップされたCellに該当するデータを抽出し、それを画面遷移する際に、遷移先に渡すのをdidSelectRowAt内で書くことが判明したものの、

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { self.navigationController!.pushViewController(self.storyboard!.instantiateInitialViewController(withIdentifier: "Article") , animated: true) }

と書いても
Cannot invoke 'instantiateInitialViewController' with an argument list of type '(withIdentifier: String)'というエラー
何が間違っているのでしょうか

該当のソースコード

import UIKit import Firebase class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var tableView: UITableView! var postArray: [PostData] = [] // DatabaseのobserveEventの登録状態を表す var observing = false override func viewDidLoad() { super.viewDidLoad() tableView.delegate = self tableView.dataSource = self let nib = UINib(nibName: "PostTableViewCell", bundle: nil) tableView.register(nib, forCellReuseIdentifier: "Cell") // テーブル行の高さをAutoLayoutで自動調整する tableView.rowHeight = UITableView.automaticDimension // テーブル行の高さの概算値を設定しておく // 高さ概算値 = 「縦横比1:1のUIImageViewの高さ(=画面幅)」+「いいねボタン、キャプションラベル、その他余白の高さの合計概算(=100pt)」 tableView.estimatedRowHeight = UIScreen.main.bounds.width + 100 } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) print("DEBUG_PRINT: viewWillAppear") if Auth.auth().currentUser != nil { if self.observing == false { // 要素が追加されたらpostArrayに追加してTableViewを再表示する let postsRef = Database.database().reference().child(Const.PostPath) postsRef.observe(.childAdded, with: { snapshot in print("DEBUG_PRINT: .childAddedイベントが発生しました。") // PostDataクラスを生成して受け取ったデータを設定する if let uid = Auth.auth().currentUser?.uid { let postData = PostData(snapshot: snapshot, myId: uid) self.postArray.insert(postData, at: 0) // TableViewを再表示する self.tableView.reloadData() } }) // 要素が変更されたら該当のデータをpostArrayから一度削除した後に新しいデータを追加してTableViewを再表示する postsRef.observe(.childChanged, with: { snapshot in print("DEBUG_PRINT: .childChangedイベントが発生しました。") if let uid = Auth.auth().currentUser?.uid { // PostDataクラスを生成して受け取ったデータを設定する let postData = PostData(snapshot: snapshot, myId: uid) // 保持している配列からidが同じものを探す var index: Int = 0 for post in self.postArray { if post.id == postData.id { index = self.postArray.firstIndex(of: post)! break } } // 差し替えるため一度削除する self.postArray.remove(at: index) // 削除したところに更新済みのデータを追加する self.postArray.insert(postData, at: index) // TableViewを再表示する self.tableView.reloadData() } }) // DatabaseのobserveEventが上記コードにより登録されたため // trueとする observing = true } } else { if observing == true { // ログアウトを検出したら、一旦テーブルをクリアしてオブザーバーを削除する。 // テーブルをクリアする postArray = [] tableView.reloadData() // オブザーバーを削除する let postsRef = Database.database().reference().child(Const.PostPath) postsRef.removeAllObservers() // DatabaseのobserveEventが上記コードにより解除されたため // falseとする observing = false } } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return postArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // セルを取得してデータを設定する let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PostTableViewCell cell.setPostData(postArray[indexPath.row]) // セル内のボタンのアクションをソースコードで設定する cell.likeButton.addTarget(self, action:#selector(handleButton(_:forEvent:)), for: .touchUpInside) return cell } //セルをタップしたら... func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // タップされたセルの行番号を出力 print("(indexPath.row)番目の行が選択されました。") //セルの選択を解除 tableView.deselectRow(at: indexPath, animated: true) //記事画面へ遷移 performSegue(withIdentifier: "Article", sender: nil) } // セル内のボタンがタップされた時に呼ばれるメソッド @objc func handleButton(_ sender: UIButton, forEvent event: UIEvent) { print("DEBUG_PRINT: likeボタンがタップされました。") // タップされたセルのインデックスを求める let touch = event.allTouches?.first let point = touch!.location(in: self.tableView) let indexPath = tableView.indexPathForRow(at: point) // 配列からタップされたインデックスのデータを取り出す let postData = postArray[indexPath!.row] // Firebaseに保存するデータの準備 if let uid = Auth.auth().currentUser?.uid { if postData.isLiked { // すでにいいねをしていた場合はいいねを解除するためIDを取り除く var index = -1 for likeId in postData.likes { if likeId == uid { // 削除するためにインデックスを保持しておく index = postData.likes.firstIndex(of: likeId)! break } } postData.likes.remove(at: index) } else { postData.likes.append(uid) } // 増えたlikesをFirebaseに保存する let postRef = Database.database().reference().child(Const.PostPath).child(postData.id!) let likes = ["likes": postData.likes] postRef.updateChildValues(likes) } } }

試したこと

[初心者向け]swiftにおける値渡しの方法の一部をご紹介を参考にしてもエラーばかりでて信用なりません。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // タップされたセルの行番号を出力 print("(indexPath.row)番目の行が選択されました。") //記事画面へ遷移 let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "Article") as! ArticleViewController //イメージ画像 nextVC.ArticleImage.image = UIImage(named:PostData[indexPath.row]) self.navigationController?.pushViewController(nextVC, animated: true) }

これだと
Value of type 'PostData.Type' has no subscripts
というエラーが出ました。

どうしてもfairebaseにあるものを渡すことができません。

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

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

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

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

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

guest

回答1

0

自己解決

①遷移元のdidSelectRowAtからデータを送る

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { //次ページにデータを送信するもの let postData = postArray[indexPath.row] postDataToSend = postData //画面遷移 performSegue(withIdentifier: "cellSegue",sender: nil) // セルの選択を解除 tableView.deselectRow(at: indexPath, animated: true) } //CommentViewControllerへデータを送る var postDataToSend: PostData? override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "cellSegue" { let commentViewController = segue.destination as! CommentViewController if let postData = postDataToSend { commentViewController.setPostData(postData) } } }

②遷移先に受け取る変数と、setPostDatという受け取り関数を書く

//前画面からデータを受け取るための変数 var postDataReceived: PostData? //前の画面からデータを継承 func setPostData(_ postData: PostData) { postDataReceived = postData }

viewWillAppearで各パーツに当てはめる

//タップされたセルのポストデータ override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) guard let postData = postDataReceived else { return } //プロフィール画像 self.profileImage.image = postData.profileImage //名前 self.nameLabel.text = postData.name //日時 let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd HH:mm" if postData.date != nil{ let dateString = formatter.string(from: postData.date!) self.dateLabel.text = dateString } //タイトル self.titleLabel.text = "(postData.caption!)" //イメージ if postData.image != nil{ self.imageView.image = postData.image } }

投稿2020/10/28 15:44

iOS25535009

総合スコア12

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問