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

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

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

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

解決済

1回答

1645閲覧

navigation controllerで値渡しができない

TsutomuTanaka

総合スコア13

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

0グッド

0クリップ

投稿2020/08/01 19:33

まだプログラミングに慣れてないので分かりにくいかと思いますが、ご容赦いただければと思います。

表題の通り、navigation controllerで画面遷移した際の値渡しがうまく行きません。
想定している挙動
→2つ目のUIViewControllerから1つ目のUIViewControllerに画面遷移した時、
テーブルビューのセルがリセットされる

1つ目のUIViewControllerの画像
イメージ説明

2つ目のUIViewControllerの画像
イメージ説明

1つ目のUIViewControllerのコード

swift

1import UIKit 2 3class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate { 4 5 @IBOutlet weak var tableView: UITableView! 6 7 var time:[String]=[ 8 "09:00", 9 "10:00", 10 "11:00", 11 "12:00", 12 "13:00", 13 "14:00" 14 ] 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 tableView.delegate = self 19 tableView.dataSource = self 20 21 22 23 24 } 25 26 override func viewDidAppear(_ animated: Bool) { 27 super.viewDidAppear(true) 28 } 29 30 31 @IBAction func editMode(_ sender: Any) { 32 if tableView.isEditing == false{ 33 return tableView.isEditing = true 34 }else{ 35 return tableView.isEditing = false 36 } 37 38 } 39 40 @IBAction func addMode(_ sender: Any) { 41 self.performSegue(withIdentifier: "settingTime", sender: nil) 42 43 44 45 time.append("aaa") 46 self.tableView.reloadData() 47 48 49 } 50 51 52 53 54 55 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 56 return time.count 57 } 58 59 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 60 let cell = tableView.dequeueReusableCell(withIdentifier: "basicStyleCell", for: indexPath) 61 62 cell.textLabel!.text = self.time[indexPath.row] 63 64 return cell 65 } 66 67 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { 68 time.remove(at: indexPath.row) 69 tableView.deleteRows(at: [indexPath], with: UITableView.RowAnimation.automatic) 70 } 71 72 73 74 75} 76 77

2つ目のUIViewControllerのコード

swift

1import UIKit 2 3class Second: UIViewController { 4 5 var time:[String]=[] 6 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 10 11 } 12 13 14 @IBAction func done(_ sender: Any) { 15 let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController 16 nextVC.time = self.time 17 self.navigationController?.popViewController(animated: true) 18 19 20 21 } 22 23 24} 25 26

なお最終的には2つ目の画像のピッカーで選択した時刻が1つ目の画像のテーブルビューに追加される挙動を目指しておりますので、そのやり方も教えていただけますと助かります。

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

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

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

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

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

guest

回答1

0

ベストアンサー

直前の画面のインスタンスを取得しようとしていますが、その方法が間違っているようです。

Swift

1 let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController 2 nextVC.time = self.time

このようにして得られた(新たに生成した)インスタンスは、既に表示されている前画面(viewController)のインスタンスとは全く異なるインスタンスですので、そのプロパティにアクセスしても前画面のインスタンスのプロパティに反映させることはできません。

したがって、既に生成済みである前画面のインスタンスを得る必要がありますが、navigationController で管理しているのであれば、管理している配列から前画面に相当するインスタンスを得て操作する必要があります。

たとえば、このような感じになります。

Swift

1class Second: UIViewController, UINavigationControllerDelegate { 2 3 // 前略 4 5 @IBAction func done(_ sender: Any) { 6 // navigationControllerで管理されている viewController は viewControllers[] に入っている 7 if let navCount = navigationController?.viewControllers.count { 8 // 直前の画面(viewController)のインデックスは、「1つ前」なので、「配列数から2を引く」 9 if let nextVC = navigationController?.viewControllers[navCount - 2] as? ViewController { 10 // ここでは直接配列に追加している 11 nextVC.time.append("20:00") 12 } 13 } 14 15 self.navigationController?.popViewController(animated: true) 16 }

インスタンスを得る方法について、最初はピンとこないかもしれませんが、navigationController で管理されている viewController は navigationController.viewControllers という配列で管理されていること、また直前の画面に相当するインスタンスは最後から2つ目に入っていることを理解できれば、ご納得いただけるかと思います。

遷移元の viewController ですが、

Swift

1 @IBAction func addMode(_ sender: Any) { 2 self.performSegue(withIdentifier: "settingTime", sender: nil) 3 // 下記のコードは削除 4// time.append("aaa") 5// self.tableView.reloadData() 6 }

上記のコードだと Segue を実行した直後に配列に値を追加し、tableView をリロードしているため、ここでは削除します。

一方、前画面から戻ってきた際に tableView を再読み込みさせるため、

Swift

1 // ビューが表示されたタイミングで tableView をリロードする 2 override func viewWillAppear(_ animated: Bool) { 3 super.viewWillAppear(animated) 4 tableView.reloadData() 5 }

のようなコードも追加する必要がありますので、ご確認ください(ちなみに、再表示の例はあくまでも例ですので、そのほかの方法もあるかと思います)。

上記以外の方法だと、たとえば UINavigationControllerDelegateプロトコルに準拠させて、シーンが切り替わるタイミングで値を渡す方法もあるのですが、それぞれ一長一短なのでとりあえずは上記の方法で良いかと思います。

投稿2020/08/02 03:07

TsukubaDepot

総合スコア5086

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問