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

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

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

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

Swift

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

解決済

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

swifty
swifty

総合スコア0

Xcode

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

Swift

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

1回答

0評価

1クリップ

977閲覧

投稿2019/07/22 16:02

編集2022/01/12 10:58

実現したいこと

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

//ChartViewを生成 let 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) let chartView = ChartView(frame: rect) //表示 self.scrollView.addSubview(chartView) //chartViewの位置を指定 scrollView.addSubview(chartView) chartView.translatesAutoresizingMaskIntoConstraints = false chartView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true chartView.topAnchor.constraint(equalTo: dailyLabel.bottomAnchor, constant: 20).isActive = true chartView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 40).isActive = true chartView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 40).isActive = true //Realmからチャート描画のためのデータを取得 ChartView.createData { recordDataArray in ChartView.lastSevenRecords = recordDataArray //期間中のスコア全て配列に格納 var scoreArray = [Int16]() for recordData in recordDataArray { scoreArray.append(recordData.score) } //期間中の最高スコアを取得 let maxScore = Int(scoreArray.max()!) if maxScore == 0 { ChartView.maxValue = 10 * 100 } else { //最高スコアを10の倍数に切り上げたものをChartViewのmaxValueに代入 ChartView.maxValue = self.getTenTimesNumber(num: maxScore, base: 10) * 100 //この100はmaxValueの値をyAxisHeightより大きくするために必要なもの } let node = ChartView.createChart() //取得したデータをチャート描画するために反映させアニメーション chartView.updateShape(node: node) chartView.contentMode = .scaleAspectFit ChartView.playAnimations() }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

hayabusabusash
hayabusabusash

2019/07/23 00:05

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

2019/07/23 02:34

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

2019/07/23 02:59

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

2019/07/23 03:13

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

2019/07/23 03:46 編集

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

2019/07/23 03:35

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

2019/07/23 03:54

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

2019/07/23 03:59

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

2019/07/23 04:03

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

2019/07/23 04:09

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

2019/07/23 04:22

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

2019/07/23 04:29

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

2019/07/23 04:33

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

まだ回答がついていません

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

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Xcode

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

Swift

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