hideyaS
@hideyaS (hideya)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【Swift】PageViewControllerに入れるViewControllerの初期化がうまくいかない

Q&A

Closed

解決したいこと

UIPageViewControllerで、3つのViewControllerを使って無限スクロールをできるようにしました。
右スワイプするたびに、ViewControllerにあるラベルの数字をカウントアップしたいのですが、
アプリが起動した時点でラベルには何も表示されません。
どうしたら初めから数字が表示されるようになるのでしょうか?

発生している問題・エラー

スクリーンショット 2022-12-21 15.30.02.png

・storybaordでViewController上にラベルを設置->ラベルはnumberLabelとしてOutlet接続
・ViewControllerのStoryboardIDを"ViewVC"に設定。
・PageViewControllerを継承したカスタムクラスで初期化

private func initPageViewController() {

        let firstVC = storyboard?.instantiateViewController(withIdentifier: "ViewVC") as! ViewController
        let secondVC = storyboard?.instantiateViewController(withIdentifier: "ViewVC") as! ViewController
        let thirdVC = storyboard?.instantiateViewController(withIdentifier: "ViewVC") as! ViewController
        
        let vcList = [firstVC, secondVC, thirdVC]
        self.vcList = vcList
        self.setViewControllers([self.vcList[0]], direction: .forward, animated: true)
        self.dataSource = self
        self.delegate = self
        
//        for i in 0...2 {
//            let viewVC = vcList[i]
//            viewVC.numberLabel.text = String(i)
//        }
    }

この時、コメントアウトしているところで"Unexpectedly found nil while implicitly unwrapping an Optional value"とエラーが出てしまう。

UIPageViewControllerDelegateの関数を用いて、
ページをスワイプする前に遷移先のViewControllerのラベルにアクセスするのもやっているが、
なぜか数が3にならないとラベルに反映されない。
つまり、上のvcListのインデックスが0,1,2と来て
また0に戻った時に初めて反映される。

func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
        let nextVC = pendingViewControllers.first as! ViewController
        number += 1
        print(number)
        nextVC.numberLabel?.text = String(number)
    }

numberは初め0。

なのでViewControllerの初期化のところで問題があるのかもしれないが、
どうやったら初期化してすぐラベルにアクセスできるかがよくわかりません。

以下に、PageViewControllerのコードを載せておきます。

InfinitePageViewController.swift
import UIKit

class InfinitePageViewController: UIPageViewController {
    
    private var vcList: [UIViewController] = []
    var number = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        initPageViewController()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
    }
    
    private func initPageViewController() {

        let firstVC = storyboard?.instantiateViewController(withIdentifier: "ViewVC") as! ViewController
        let secondVC = storyboard?.instantiateViewController(withIdentifier: "ViewVC") as! ViewController
        let thirdVC = storyboard?.instantiateViewController(withIdentifier: "ViewVC") as! ViewController
        
        let vcList = [firstVC, secondVC, thirdVC]
        self.vcList = vcList
        self.setViewControllers([self.vcList[0]], direction: .forward, animated: true)
        self.dataSource = self
        self.delegate = self
        
//        for i in 0...2 {
//            let viewVC = vcList[i]
//            viewVC.numberLabel.text = String(i)
//        }
    }

}

extension InfinitePageViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        let nowIndex = self.vcList.firstIndex(of: viewController)
        let nextIndex = (nowIndex! + 1) % 3
        let nextVC = self.vcList[nextIndex] as! ViewController
//        nextVC.numberLabel.text = String(nextIndex)
        return nextVC
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let nowIndex = self.vcList.firstIndex(of: viewController)
        let backIndex = (nowIndex! - 1 + 3) % 3
        let backVC = self.vcList[backIndex] as! ViewController
//        backVC.numberLabel.text = String(backIndex)
        return backVC
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
        let nextVC = pendingViewControllers.first as! ViewController
        number += 1
        print(number)
        nextVC.numberLabel?.text = String(number)
    }
    
}

以上よろしくお願いします。

0

1Answer

設定したい値をViewControllerのプロパティに持たせてviewDidLoad()で設定してはいかがでしょうか。

0Like

Comments

  1. @hideyaS

    Questioner

    同じViewControllerを3回呼んでいるので、それだと一つの値しか設定できなくなってしまいます。
  2. インスタンスは別なのでそうはならないのではないでしょうか。
  3. @hideyaS

    Questioner

    おっしゃる通りで、
    インスタンスごとにラベルにアクセスしてエラーが起きてしまいました。
    viewDidLoad()だと、ViewControllerファイルが一つしかないので
    三つの値をそれぞれ設定するのが難しいかと思いました。
  4. `viewVC.numberLabel.text = String(i)` の代わりに例えば `viewVC.number = i` のようにしたら良いのではというコメントだったのですが伝わっていますか?
  5. @hideyaS

    Questioner

    お手数おかけしました。
    お教え頂いたアイデアで解決しました。
    ありがとうございました。

Your answer might help someone💌