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

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

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

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

Swift

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

Q&A

解決済

1回答

1802閲覧

PageViewControllerで特定ページへの2回目以降のスワイプでの遷移時も1度目遷移したときのような挙動を実現する方法

swifty

総合スコア38

Xcode

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

Swift

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

0グッド

1クリップ

投稿2019/07/22 16:02

編集2019/07/23 03:55

実現したいこと

PageViewControllerを使って3ページで構成されているAppを実装しております。

その2ページ目から3ページ目に初めてスワイプして遷移したときと全く同じ挙動を毎回2ページ目から3ページ目に遷移するときはさせたいです。

発生している問題

  1. CalendarViewController
  2. TodayViewController
  3. RecordViewController

ページは上の3ページで構成されており、ページ2でデータの変更&保存ができます。3ページ目はその保存されたデータを元にチャートを表示するようにしております。

初期表示が2ページ目になっており、初めて2ページ目から3ページ目にいくときは2ページ目で変更や保存したデータが適切にチャートで表示されます。

ですがその後スワイプでページ2に戻ってから、データを更新してページ3にいくとその結果が反映されず、先ほど表示されたチャートがそのまま表示されてしまいます。

どのようにすれば毎回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 // self.delegate = self } 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) { // if completed { // guard let recordViewController = pageViewController.viewControllers?.first as? RecordViewController else { // return // } // // // Ver 1 (recordViewControllerをviewDidLoad()) // recordViewController.viewDidLoad() // // // Ver 2 (recordViewControllerのscrollView内のsubviews(こちらに削除する複数のチャートが含まれています)を削除してからviewDidLoad()) // let subviews = recordViewController.scrollView.subviews // // for subview in subviews { // subview.removeFromSuperview() // } // // recordViewController.viewDidLoad() // // // } // } //}

試したこと

teratail上で前回ご質問させていただきまして、上のソースコードでコメントアウトしているUIPageViewControllerDelegateメソッドを使うことでスワイプでのページ遷移ごとに毎回データを更新することはできるようになりました

ただViewの表示が思ったようにはできませんでした。

Ver1, Ver2とそれぞれ試してみましたが

Ver1 → チャートの上にもう1度同じチャートが上書きされてしまうだけ
Ver2 → 上書きはされなくなり、チャートは表示されるがその表示が適切ではなくデータにそぐわないもので、View全体のLayoutも崩れてしまい、カクカクした感じがあり、チャート描画のアニメーションもおかしい

など様々な問題が起き理想の挙動が実現できなかったためもっとシンプルに考えて

初めて2ページ目から3ページ目に行くときの挙動は完璧なので毎回2ページ目から3ページ目にいくときはそのときと同じ挙動にすれば全てが解決するのではないかと考えました。

ただその方法がわかりかねております。それさえわかればその方法をDelegateメソッドに書くことで解決できるのではないかと考えております。

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

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

Swift 5.0.1
Xcode 10.2.1

情報の追加・修正依頼を受けての追記

RecordViewControllerのチャート生成部分の記述は以下のようになっております。

RecordViewController

1//ChartViewを生成 2let rect = CGRect.init(x:((self.view.bounds.width-self.view.bounds.width * 0.9)/2), y: 175, width: self.view.bounds.width * 0.9, height: 500) 3let chartView = ChartView(frame: rect) 4 5//表示 6self.scrollView.addSubview(chartView) 7 8//chartViewの位置を指定 9scrollView.addSubview(chartView) 10chartView.translatesAutoresizingMaskIntoConstraints = false 11chartView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true 12chartView.topAnchor.constraint(equalTo: dailyLabel.bottomAnchor, constant: 20).isActive = true 13chartView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 40).isActive = true 14chartView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 40).isActive = true 15 16//Realmからチャート描画のためのデータを取得 17ChartView.createData { recordDataArray in 18 19 ChartView.lastSevenRecords = recordDataArray 20 21 //期間中のスコア全て配列に格納 22 var scoreArray = [Int16]() 23 for recordData in recordDataArray { 24 25 scoreArray.append(recordData.score) 26 27 } 28 29 //期間中の最高スコアを取得 30 let maxScore = Int(scoreArray.max()!) 31 32 if maxScore == 0 { 33 34 ChartView.maxValue = 10 * 100 35 36 } else { 37 38 //最高スコアを10の倍数に切り上げたものをChartViewのmaxValueに代入 39 ChartView.maxValue = self.getTenTimesNumber(num: maxScore, base: 10) * 100 //この100はmaxValueの値をyAxisHeightより大きくするために必要なもの 40 41 } 42 43 let node = ChartView.createChart() 44 //取得したデータをチャート描画するために反映させアニメーション 45 chartView.updateShape(node: node) 46 chartView.contentMode = .scaleAspectFit 47 ChartView.playAnimations() 48 49}

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

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

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

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

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

hayabusabusash

2019/07/23 00:05

RecordViewControllerがどんな感じになっているのか分かりませんが、 チャートの更新の処理をViewWillAppear()で行うようにするのはどうでしょうか?
swifty

2019/07/23 02:21

お世話になります。 ご回答ありがとうございます。 早速実装させていただきました。 ViewWillAppear()にて更新処理を行うことでページをめくる度にデータの更新処理が行われ、アニメーションも再度行われるようにできました。 ただ、UIPageViewControllerDelegateメソッドのVer1を使用した際と同じで先ほど描画したチャートの上にアニメーションをしてから上書きする挙動になってしまいます。(View Debugging→Capture View Hierarchyで確認するとチャートの上に全く同じチャートがもう1つ表示されていました) RecordViewControllerでは Macaw ( https://github.com/exyte/Macaw ) というチャート描画ライブラリを利用していて複数のチャートを描画しております。RecordViewControllerからはチャートに使われるデータは更新された適切な数値がかえってきているのですがview上では描画されるチャートの長さはデータ変更前と変わらない先ほど描いたものをもう一度なぞるだけになってしまっております。 取得し表示するためのデータの更新などはうまくいっているのであとはこのチャートが上書きされていかないようにさえできればいいのですが...
hayabusabusash

2019/07/23 02:34

返信ありがとうございます! 上書きの挙動ですが、 Macaw公式のドキュメントの例にあるグラフをそのまま使っているなら、 更新をするような処理はないのでMacawのグラフを表示しているViewを削除(subViewも含め)して、 再度1から描画するという処理が必要になるんじゃないかなと思います。 Macawは図形描画やアニメーションなど幅広くカバーしていますが、 書き方に癖があって個人的には少しやりづらいと思うので、 以下から良さげなものを見つけて使ってみてはどうでしょうか? ( https://github.com/search?q=swift+graph )
swifty

2019/07/23 02:59

ご回答ありがとうございます。 その通りなんです。Charts ( https://github.com/danielgindi/Charts/issues/189 ) などと違って Macawには更新をするような処理がないので悩ましいです。 "Viewを削除(subViewも含め)して、再度1から描画するという処理が必要になるんじゃないかなと思います。" →その通りです。今自分でもviewDidDisappearでtag付けしておいたチャートのViewだけ消すということをすることで重なっていくということは避けることはできました。これで全て解決かと思われたのですが、なぜか描画されるチャートデータだけ更新前に描かれるものと変わっていません。中身のデータは問題なく更新されているのですが。 たしかにMacawを使ってきていいところもあるのですが、大分癖が強いということもわかってきたので他のライブラリの導入も検討させていただきます。 ご提案ありがとうございます。 ただあともう少しなのでもう少しやり方を自分なりにも考えてみたいと思います。
hayabusabusash

2019/07/23 03:13

なるほど。もう少しで解決できそうですね。 チャートの描画の部分のコードを質問のところに載せていただくことはできますか?
swifty

2019/07/23 03:46 編集

ありがとうございます。 いろいろカットはしてあるものの少し長くなりますがこのようにして描画しております。 コードを質問部分に追記させていただきました。 ご不明な点ございましたらお伝えいただけますと幸いです。
hayabusabusash

2019/07/23 03:35

lastSevenRecordsに表示させたいデータが入る感じですか? あと、追加でChartViewの方のコードも見せていただけないでしょうか?
swifty

2019/07/23 03:54

お世話になっておりおります。 その通りです。lastSevenRecordsにデータが入ります。 ページめくるたびにこちらのlastSevenRecordsはprintすると適切に更新されています。 ChartView側ものせたいのですがコードの量が膨大になってしまうので1度こちらまでとさせていただければと思います。 動きとしてはシンプルで ①createData   表示するためのデータを準備 ②createChart()   チャートを生成 ③playAnimations()   アニメーション の3段構成となっております。 引き続き何卒よろしくお願いします。
hayabusabusash

2019/07/23 03:59

もしかしてcreateDataやcreateChartってstaticの関数ですか?
swifty

2019/07/23 04:03

そうです!それが問題なのでしょうか?
hayabusabusash

2019/07/23 04:09

そうですね、そこが少し怪しいです。 ChartViewを生成のコメントのあたりでchartViewのインスタンスを生成していますが、 これが更新されていないような感じがします。 そもそもstaticの関数が色々混じっているので、 何が更新されてどうなっているのかが掴みにくいと思います。 まずはその辺りを普通の関数に戻してみたりするのはどうでしょうか? 少なくともcreateChartはstaticにしなくてもいいと思います。
swifty

2019/07/23 04:22

ありがとうございます。 なるほど。 たしかに怪しいですね。 今早速staticなしで全て書きかえてみております。出来次第コメントさせていただきます。
swifty

2019/07/23 04:29

完璧です!!!! 無事問題が解決されました!!!! hayabusabusashさまの読みの通りだったようです! 完璧な挙動が実現できました! 本当に感動しております! ありがとうございました!
swifty

2019/07/23 04:33

hayabusabusashさまにベストアンサーをつけさせていただきたいのですが質問への追記・修正の依頼部分でやりとりしていたためベストアンサーがつけられない状況です! もしよろしければ回答の部分に何か記述していただけませんでしょうか? ベストアンサーにさせていただきます。 何卒よろしくお願いします!!
guest

回答1

0

ベストアンサー

ChartViewcreateChart()staticの関数になっていて、
生成したChartViewのインスタンスが更新されていなかったのが原因だったようです。

解決できたみたいでよかったです!

投稿2019/07/23 04:38

hayabusabusash

総合スコア767

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

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

swifty

2019/07/23 04:47

hayabusabusashさま ご回答ありがとうございました! 感謝してもしきれません。本当にありがとうございました! 自分にとってとても乗り越えるのが難しい大きい壁でしたので感動もひとしおです。 今後とも何かありましたときは何卒よろしくお願いします。 私も精進して参ります! みなさまへ こちらの回答についての詳細は「質問への追記・修正依頼」のコメントのやりとりを参考にしていただけますと幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問