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

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

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

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

Swift

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

Q&A

解決済

2回答

9466閲覧

Swiftにて、modalをdismissしたタイミングで親ViewのtableviewをreloadDataしたい。

namatay

総合スコア12

Xcode

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

Swift

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

0グッド

2クリップ

投稿2018/09/26 08:54

編集2018/09/26 09:44

Swiftにて、modalをdismissしたタイミングで親ViewのtableviewをreloadDataしたいと思います。

前提条件

親viewでは展開時に処理待ちの通知の一覧をAPIから取得してきてtableviewに表示。
tebleviewcell内のボタンで処理内容を選択し、処理内容に応じmodalを展開。
親view内の通知一覧の画面表示内容を更新しないとならないので
modalの戻るボタンを押したタイミングで、親view展開時の描画のfunctionを実行している。

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

modalを閉じた際に self?.tableView.reloadData() が動作しない。
self?.tableViewがnilになってしまっている。

該当のソースコード

親view

swift

1 2class NotificationViewController: UIViewController { 3 4〜中略〜 5 6 func refresh(){ 7 if let loginData = self.loginData, 8 let accountId = loginData.accountId { 9 self.accountId = accountId 10 } 11 12 self.alerts = [] 13 self.sendAlerts() 14 } 15} 16 17extension NotificationViewController { 18 func sendAlerts() { 19 20〜中略〜 21 22 let parameters = ["account_id": self.accountId] 23 API.Messages.alerts(parameters: parameters) 24 .response({ [weak self] result in 25 switch result { 26 case let .response(message): 27 self?.alerts = message.alerts 28 DispatchQueue.main.async { 29 self?.tableView.reloadData() 30 if message.alerts.count == 0 { 31 AlertUtility.showConfirm(viewController: self, message: NSLocalizedString("noNotificationFailure", comment: "noNotificationFailure")) 32 } 33 } 34 case let .error(reason): 35 DispatchQueue.main.async { 36 AlertUtility.showError(viewController: self, message: NSLocalizedString("alertsFailure", comment: "alertsFailure")) 37 } 38 } 39 }) 40 self.reloadButton.isEnabled = true 41 } 42 43

モーダル

swift

1 2class PopupViewController: UIViewController { 3 4〜中略〜 5 6 @IBAction func okDate_Action(_ sender: Any) { 7 dismiss(animated: true) 8 guard let parent = storyboard?.instantiateViewController(withIdentifier: "NotificationViewController") as? NotificationViewController else { 9 fatalError() 10 } 11 parent.refresh() 12 } 13} 14

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

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

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

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

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

fuzzball

2018/09/26 08:58

「self?がnilになってしまっている」の根拠は?
namatay

2018/09/26 09:00

ブレークポイントをつけて処理を止めてみたのですが、その際に確認しました。
fuzzball

2018/09/26 09:01

ブレークポイントをどこに付けたのでしょうか?
namatay

2018/09/26 09:03

親viewで self?.tableView.reloadData()を実行している行ですね。
guest

回答2

0

viewWillAppearでrefresh()

モーダルから戻ってきたときにviewWillAppear(:)が呼ばれますので、この中でrefresh()を呼ぶようにしましょう。
モーダルから戻ってきたとき以外にもviewWillAppear(
:)は呼ばれますので、presentedViewControllerを見て処理を分岐します。これには、呼び出していたモーダルのViewControllerが入っています。それ以外のときはnilです。

swift

1override func viewWillAppear(_ animated: Bool) { 2 super.viewWillAppear(animated) 3 4 if let presented = self.presentedViewController { 5 if type(of: presented) == PopupViewController.self { 6 //PopupViewControllerから戻ってきたときはrefresh() 7 self.refresh() 8 } 9 } 10}

旧回答

swift

1guard let parent = storyboard?.instantiateViewController(withIdentifier: "NotificationViewController") as? NotificationViewController else {

これは新しいインスタンスを生成していますので、呼び出し元のNotificationViewControllerとは別物です。なぜselfがnilになるのかまでは調べていません。

モーダルの場合はpresentingViewControllerで呼び出し元のViewControllerを取得できますので、下記のコードでrefresh()を呼び出せると思います。

swift

1if let parent = self.presentingViewController as? NotificationViewController { 2 parent.refresh() 3}
別の方法

2日前の出来事です。
Swift (Xcode): modal dismissと同時に親Viewを再描画(refresh)させたい

投稿2018/09/26 09:00

編集2018/09/27 00:22
fuzzball

総合スコア16731

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

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

namatay

2018/09/26 09:26

ご教授ありがとうございます。早速試してみます。
fuzzball

2018/09/26 09:27

NotificationViewControllerの名前を間違えていたので修正しました。
daisuke7

2018/09/26 09:45

guard let parent = storyboard?.instantiateViewController(… で作成した parent は誰にも保持されないまま refresh() を呼び出すので、okDate_Action()を抜けると同時に破棄。 refresh()はAPI.Messages.response() のコールバックを設定するけど、コールバックに飛び込んできたときにはすでにparentだったものは破棄されている。 だから weak self では nil になってしまうのでは。
namatay

2018/09/26 09:47

モーダルの方のviewcontrollerがこうなりました。 @IBAction func okDate_Action(_ sender: Any) { dismiss(animated: true) if let parent = self.presentingViewController as? NotificationViewController { parent.refresh() } } ただif文で引っかかってくれませんね…。
fuzzball

2018/09/26 16:14 編集

>>daisuke7さん おそらくそんなところだろうとは思うのですが、さすがに検証までする気は無いのでしたw 動いている最中に破棄されるのかな?と思ったり、[weak self] これが破棄OKなのかな?と思ったりしつつ。 【追記】weak selfについて書かれているのを見落としてました。すみません。
fuzzball

2018/09/26 09:51

>>namatayさん もしかしてナビゲーションコントローラ使ってます?
namatay

2018/09/26 10:02

思いっきり使ってますorz これ前任者から引き継いだソースなんで少々陳腐なもの使ってる節があるんですが… navigation controller使ってるとparentが多分そっちに持って行かれてしまうので、 取り敢えずモーダルの閉じるボタンからNotificationViewControllerに返すのが 正解なんでしょうか。
xAxis

2018/09/26 13:04

あれー?なんだか見覚えある命名だなーとか思ったらリンク先でワロタ
fuzzball

2018/09/27 00:23

viewWillAppear(_:)を利用した回答を書きました。
guest

0

自己解決

ひとまずnavigationControllerを使ってしまっているため今回は諦めました。
お知恵をいただいていながら申し訳ありませんです。
次回からは気をつけて開発に挑みます。
ありがとうございました。

投稿2018/09/27 03:54

namatay

総合スコア12

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

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

fuzzball

2018/09/27 03:56

今朝追記した回答はナビゲーションコントローラを使っていても対応できますが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問