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

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

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

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

Swift

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

Q&A

解決済

1回答

1610閲覧

PageViewController使用時にPageをめくるごとにViewを更新する方法

swifty

総合スコア38

Xcode

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

Swift

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

0グッド

0クリップ

投稿2019/07/21 02:28

編集2019/07/21 02:30

実現したいこと

PageViewController使用時、Page遷移するたびにViewを更新したいです。

発生している問題

PageViewControllerを使いスワイプでページがめくれるよう実装しております。
3ページで構成されており、左から

  1. CalendarViewController
  2. TodayViewController
  3. RecordViewController

となっております。ページ2でデータの変更&保存ができます。3ページ目はその保存されたデータを表示するようにしております。

初期表示が2ページ目になっており、2ページ目から初めて3ページ目に行くときは2ページ目で変更や保存したデータが適切に表示されます。ですがその後ページ2に戻ってから、データを更新してページ3にいくとその結果が反映されず、先ほど表示されたデータがそのまま表示されてしまいます。

どのようにすれば2ページ目から3ページ目に行くたびに更新されたデータを表示できますでしょうか?

該当のソースコード

import UIKit class PageViewController: UIPageViewController { override func viewDidLoad() { super.viewDidLoad() self.setViewControllers([getTodayPage()], direction: .forward, animated: true, completion: nil) self.dataSource = self // let todayViewController = TodayViewController() // pageViewController(self, didFinishAnimating: true, previousViewControllers: [todayViewController], transitionCompleted: true) } func getTodayPage() -> TodayViewController { let todayView = storyboard!.instantiateViewController(withIdentifier: "todayViewIdentifier") as! TodayViewController todayView.selectedDate = selectedDate return todayView } func getCalendarPage() -> CalendarViewController { return storyboard!.instantiateViewController(withIdentifier: "calendarView") as! CalendarViewController } func getRecordPage() -> RecordViewController { return storyboard!.instantiateViewController(withIdentifier: "recordView") as! RecordViewController } } extension PageViewController : UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { if viewController.isKind(of: RecordViewController.self) { return getTodayPage() } else if viewController.isKind(of: TodayViewController.self) { return getCalendarPage() }else{ return nil } } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { if viewController.isKind(of: CalendarViewController.self) { return getTodayPage() } else if viewController.isKind(of: TodayViewController.self) { return getRecordPage() }else{ return nil } } } //extension PageViewController: UIPageViewControllerDelegate { // // func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { // // //Ver 1 // let recordViewController = RecordViewController() // recordViewController.viewDidLoad() // // //Ver 2 // pageViewController.dataSource = nil // pageViewController.dataSource = self // // } //}

試したこと

上のソースコードでコメントアウトしているUIPageViewControllerDelegateを使った方法でVer1, Ver2とそれぞれ試してみましたがどちらも結果は変わりませんでした。

他にもviewWillAppearとviewDidDisappearをoverrideするなど様々な方法を試してみましたが思うような結果が得られませんでした。

皆様のお力添えいただけますと幸いです。
何卒よろしくお願いいたします。

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

Swift 5.0.1
Xcode 10.2.1

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

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

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

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

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

guest

回答1

0

ベストアンサー

Ver1, 2では新たにインスタンスを生成しているためデータが更新されていません.
pageViewControllerからページを取得する必要があります.

Swift

1func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { 2 if completed { 3 let recordViewController = pageViewController.viewControllers.first //必要に応じてキャスト,例外処理を追加してください. 4 recordViewController.表示更新処理() 5 } 6}

別の方法として,
NotificationCenterを利用し,TodayViewControllerでデータの変更があれば通知を送信.
RecordViewControllerで通知を受信するとデータを書き換えるという方法もあります.
参考
【Swift】NotificationCenterの使い方

投稿2019/07/21 08:04

rcftdbeu

総合スコア167

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

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

swifty

2019/07/21 09:43 編集

お世話になります。 早速実装してみました。 記述していただきました func(表示更新処理()とある部分にはviewDidLoad()と記述) を私が記述したコードでコメントアウトしてあるextension内の func と書き換え、recordViewControllerのviewDidLoad()内に let pageViewController = PageViewController() let todayViewController = TodayViewController() pageViewController.pageViewController(pageViewController, didFinishAnimating: true, previousViewControllers: [todayViewController], transitionCompleted: true) を書きました。delegateメソッドは呼ばれるのですが思った動きをしない状況です。func内の recordViewController をprintしてみるとnilになっているのでここをRecordViewControllerにしたいのですができかねております。 度々大変恐縮ですがお力添えいただけますと幸いです。 何卒よろしくお願いします。
rcftdbeu

2019/07/21 11:32

こちらの動作環境ではPageViewControllerのviewDidLoad内に self.delegate = self を追加した後に,以下のコードで動作を確認しましたがページ遷移時に意図した通りに動いています. こちらのコードで動作するかご確認いただけないでしょうか. ---該当コード--- extension PageViewController: UIPageViewControllerDelegate { func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { if completed { guard let recordViewController = pageViewController.viewControllers?.first as? RecordViewController else{ return } recordViewController.viewDidLoad() } } } ---
swifty

2019/07/21 14:22

ご回答ありがとうございました。 ご回答いただいたコードで動かしたところデータが更新されるようになりました! ありがとうございます! ただそこでもう1つ問題が出てきておりましてその問題と格闘していたところ返事が遅れてしまいました。 申し訳ございません。 3ページ目のrecordViewControllerでは3つのUIView(2ページ目のデータに基づくChart)を生成しているのですがその部分だけずっとChartの上にChartが上から書き足されていくといった状態になってしまっております。 recordViewController内のviewDidLoad内でChartの描画を行なっているので recordViewController.viewDidLoad() でもう1度まっさらな状態からViewが生成されて表示されて全てうまくいくと思っていたのですがそうはなりませんでした。 生成した3つのUIViewはstoryboardで作ったscrollViewにaddsubviewを使って追加して表示しているので 単純にそれをremoveしてもう一度ロードしなおせばいいのではないかと考え recordViewController.scrollView.removeFromSuperview() recordViewController.viewDidLoad() と書き換えてみたりもしたのですがクラッシュしてしまっております。 こちらの問題については質問内容が本来の質問の主旨と違うのでもしお分かりになればで構いませんのでもしお分かりになりましたら教えていただけますと幸いです。 自分でももう少しいろいろ試してみて解決できなそうであればまたもう1度新たにページを作って質問を投げかけさせていただこうと思います。 ひとまずデータの更新はできるようになりましたので先に進むことができました。 本当にありがとうございました!!
swifty

2019/07/21 14:42

お世話になっております。 上のコメントで書かせていただきました問題の件ですが let subviews = recordViewController.scrollView.subviews for subview in subviews { subview.removeFromSuperview() } recordViewController.viewDidLoad() としたところanimationの表示がおかしくなっていたり、AutoLayoutがバグってしまったりといくつか問題はありますが適切な表示がページ遷移の度になされるようになりました。 報告までに。 本当にありがとうございました!!
rcftdbeu

2019/07/22 10:55

動作するようになって良かったです. Chartの生成方法にもよりますが,データを更新する方法があれば, ・viewDidLoadでは生成とデータ更新 ・ページ遷移時はデータ更新のみ とするとよくなると思います.
swifty

2019/07/22 12:05

ご回答ありがとうございます。 感謝の気持ちでいっぱいです。 今も問題と向き合っていたのですがなかなか難しく感じております。 個人的にもページ遷移時はデータの更新のみというのが理想なのですが、チャートのY軸の表示の値も表示されるデータによって動的にかわるという実装をしているため新たなChartの生成も必須に感じております。 一度自分の頭の中で問題点が整理できたら新しいページを作って質問させていただこうと思います。
swifty

2019/07/22 13:40

お世話になっております。 いろいろ試してみたのですが解決できかねておりますのでこちらでもう1度質問させていただければと思います。 ChartのUIviewだけの再生成&挿入などを考えて実装しようと試みていたのですが複数のチャートや他の複数のLabelとの位置関係をAutolayoutでコードで書いていることもあり、それをしようとするとLayoutが崩れてしまう問題にもぶつかりましたので少しシンプルに考えてみました。 1番始めに2ページ目から3ページ目に行くときの挙動は完璧なので毎回2ページ目から3ページ目にいくときはそのとき(初めて2ページ目から3ページ目にいくとき)と同じ挙動にすれば全てが解決するのではないかと考えました。 ただそれが自分では recordViewController.viewDidLoad() することしか思い当たりません。ただそれだと前にも書かせていただいたように上書きのようなものになってしまい適切な表示がなされません。 初めて2ページ目から3ページ目にいったときの挙動を再現するにはdelegateメソッド内でどのような記述をすればよいでしょうか? 度々大変恐縮ですがお力添えいただけますと幸いです。
swifty

2019/07/23 05:22

こちらの問題以下の新たに作らせていただきました質問を通して無事解決することができました。 https://teratail.com/questions/202009 こちらのステップに進めためのご回答感謝しております。 お力添えありがとうございました。
rcftdbeu

2019/07/23 12:14

ご連絡ありがとうございます. 私だとstaticにたどり着けなかったかもしれないです. 解決して良かったです.
swifty

2019/07/24 07:32

お世話になっております。 私もまさかstaticが問題だったとは思いもしませんでした。 言われてみればたしかに。という感じでしたがまだまだ視野が狭くなってしまっていることがあるので一歩一歩精進していきたいと思います。 今後とも何卒よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問