前提・実現したいこと
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にあるものを渡すことができません。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。