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

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

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

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

Q&A

1回答

2693閲覧

dismissを使うと値が反映されなくなる

daxelbook

総合スコア1

Swift

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

0グッド

0クリップ

投稿2020/10/07 16:04

編集2020/10/07 16:06

前提・実現したいこと

https://qiita.com/pe-ta/items/8f474358d1dd789557f3
こちらのチュートリアルをやっています。
モーダルビュー内でUITextfieldに値を渡した後にビューを閉じたいです

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

dismiss(animation: true)を使用して閉じると入力した値が反映されない

該当のソースコード

Swift

import UIKit var todoArray = [String]() class AddController: UIViewController { @IBOutlet weak var todoTextField: UITextField! @IBAction func todoAddButton(_ sender: Any) { todoArray.append(todoTextField.text!) todoTextField.text = "" UserDefaults.standard.set(todoArray, forKey: "todoList") dismiss(animated: true) } @IBAction func dismissModal(_ sender: Any) { dismiss(animated: true) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destination. // Pass the selected object to the new view controller. } */ }

試したこと

todoAddButtonのスコープ内で処理の順番を入れ替えたりしたのですが上手く行かず...
エラーも出てないので何が上手く行ってないのか分からずといった状況です...

補足情報(FW/ツールのバージョンなど)

Xcode 12.0

イメージ説明

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

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

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

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

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

TsukubaDepot

2020/10/07 23:23

Qiitaの記事と比較すると、 dismiss(animated: true) が追加されていますが、これはご自身で追加されたコードでしょうか。 また、 ViewController の方のコードはどのようになっていますでしょうか。 ViewController のコードについては、ご質問本文に追加していただければと思います。
mskRR

2020/10/11 16:56

UIAdaptivePresentationControllerDelegateらへんの知識のアップデートをされてはいかがでしょうか?
guest

回答1

0

参照している記事は、「追加画面」の左上に配置されている「戻る」ボタンから「メイン画面」にsegueの線を引っ張って画面遷移しています。この場合、元々表示していた「メイン画面」に戻るのではなく、新しい「メイン画面」を作成して、そこに画面遷移する動作が行われます。新しい画面に画面遷移した時は、 viewDidLoad メソッドが呼ばれますので、viewDidLoad の中で実施されているUserDefaults読み込み処理によって最新の保存状態が読み込まれ、「追加画面」で保存した結果が「メイン画面」に表示されるようになっています。

しかし、この記事のやり方はするべきではありません。この方法だと、元々表示していた「メイン画面」に戻ることがなく、「戻る」ボタンを押すたびにどんどん新しい「メイン画面」が生成されてしまいます。さらに「追加画面」も画面遷移先から戻ってくるのを待っている状態になり、画面遷移するたびに、戻りを待っている「メイン画面」と「追加画面」がどんどん生成され、無駄なメモリ消費がどんどん行われてしまいます。

画面を戻る処理は、daxelbookさんがやろうとされている通りdismissメソッドを使う(またはexitにsegueを接続する)方法でやるべきです。そうすれば、画面を戻る処理がちゃんと行われ、「追加画面」が破棄されて、元々表示していた「メイン画面」に戻ってそれが表示されるようになります。

dismissで戻る方法がうまく行っていない原因は、 UserDefaults読み込み処理が viewDidLoadで行われており、viewDidLoad は新しい画面を表示した時に一度だけ呼ばれるメソッドで、画面に戻った時はviewDidLoadが呼ばれず、UserDefaults読み込み処理が行われないためです。

画面を戻った時に最新の状態を画面に反映したい場合は、 viewWillAppearメソッドの中で最新のデータを読み込んで画面に反映する処理を実施する必要があります。

次のようにviewWillAppearメソッドの中でUserDefaultsを読み込み、TableViewの更新を指示すれば、dismissで戻った時に保存した結果が正しく表示されるようになると思います。(tableViewは、Storyboardからoutlet接続する必要があります。)

swift

1override func viewWillAppear(_ animated: Bool) { 2 //追加画面で入力した内容を取得する 3 if UserDefaults.standard.object(forKey: "TodoList") != nil { 4 TodoKobetsunonakami = UserDefaults.standard.object(forKey: "TodoList") as! [String] 5 } 6 tableView.reloadData() 7}

Qiitaの記事は、大変有用なものもありますが、一方で誰でも記事を書いて公開できるので、あまり理解していない人が初心者向けに丁寧な記事を書いて、おかしなやり方を広めてしまっていることもあります。今回参照されている記事は、画面遷移のことをあまり理解していない人が安易に書かれているように思います。画面遷移のことをちゃんと理解している人なら、メイン画面に逆方向のsegueを接続するようなやり方は絶対にしません。また、UINavigationContollerを使わずにUINavigationBarを直接貼り付けているのも気になります。これだと、後でiPhoneX系の画面にUINavigationBarをうまくレイアウトさせるのに苦労するだろうなと思います。

市販の入門書籍を購入する等、できるだけ信頼できる情報を使って勉強することをお勧めします。


(2020/10/9追記)

TsukubaDepotさんからコメント欄でご指摘を頂いた通りですが、iOS13以降のモーダル画面遷移は遷移元画面の上端が見えた状態で遷移するので、画面を戻った時にviewWillAppearが呼ばれません。画面遷移先のViewControllerのPresentationをFull Screenと設定すれば遷移元画面が見えない状態で画面遷移するので画面を戻った時にviewWillAppearが呼ばれるようになります。

画面遷移時に遷移元画面の上端が見えた状態で遷移させたい場合は、unwindSegue(exitにsegueを接続する方法)で画面を戻った時に呼ばれるメソッドでUserDefaults読み込み処理を行う(TsukubaDepotさんのリンク参照)か、あるいは
https://qiita.com/ichikawa7ss/items/df8cd87e66ada42cb560
で説明されているように、画面遷移時にUserDefaults読み込み処理が記述されたクロージャを渡し、画面を戻る時にそのクロージャを呼び出す方法があります。

投稿2020/10/08 10:56

編集2020/10/08 15:24
TakeOne

総合スコア6299

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

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

TsukubaDepot

2020/10/08 11:29

iOS13以降でモーダル表示していなければ、遷移元に戻ったときに viewWillAppear が呼び出されない可能性があるかと思います。 https://teratail.com/questions/273179 なので、前半でご指摘されていた exit に接続した上、unwindSegue を使った方が安全かと思っています。 あるいは、遷移先の画面のインスタンスを作成し、遷移方法を modalPresentationStyle = .fullScreen にする方法もあるかと思います。 最後の Qiita 記事についてのご指摘はごもっともだと思います。 私もこの記事を見ていて気になっていました。 一方、質問者さんのコードを見ると、きちんと dismiss で閉じているので、もしかしたらその辺りの理解はされているのかもしれないとも感じていたところです(質問へのコメントに書いていたので、ご本人が気づかれたらコメントがあるかもしれません)。
TakeOne

2020/10/08 15:25 編集

TsukubaDepotさん、ご指摘ありがとうございます。iOS13以降のモーダル画面遷移の話をうっかり忘れていました。回答に追記させていただきました。
daxelbook

2020/10/08 17:42

TakeOne様、TsukubaDepot様、大変ご丁寧な回答ありがとうございます。 dismissは別のチュートリアルで学んだメソッドですがよく仕組みを理解しないまま組み込んでいたので今こういうことになっているようです.... viewWillAppearやunwindSegue等、聞き慣れない言葉が出ていて少し混乱しているためもう少し公式ドキュメントを読み込んでまた理解を深めようと思います。 チュートリアルから学ぶ際の姿勢も教えてくださり大変ためになりました....。もう少し有用な学び方を模索してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問