Home > Back-end >  Can't reload next ViewController in PageViewController
Can't reload next ViewController in PageViewController

Time:04-09

I can't update next page in my PageViewController.

  1. I add the required number of controllers, but the pageController.setViewControllers([controllers[0]], direction: .forward, animated: false) method leaves us with one.

  2. I have information for each next controller taken from the viewModel and updated when the currentIndex counter changes

  3. In the viewControllerBefore and viewControllerAfter methods, I initialize my view controller and increase or decrease currentIndex when scrolling forward or backward

  4. After that, the didSet in the view controller works for me and the update takes place.

  5. But, in the end, instead of 8 controllers, I only see 2.

PageViewController

class PageViewController: UIViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {

let viewModel: GeneralViewModel

let locationViewModel: LocationViewModel

let realm = try! Realm()

var pageControl = UIPageControl.appearance()

var pageController: UIPageViewController!

var controllers = [UIViewController]()

var pendingIndex = 0

init(viewModel: GeneralViewModel, locationViewModel: LocationViewModel) {
    self.viewModel = viewModel
    self.locationViewModel = locationViewModel
    super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
    super.viewDidLoad()
    
    pageController = UIPageViewController(transitionStyle: .scroll,
                                                  navigationOrientation: .horizontal,
                                                  options: nil)
    pageController.delegate = self
    pageController.dataSource = self
    
    
    
    addChild(pageController)
    view.addSubview(pageController.view)
    
    let views = ["pageController": pageController.view] as [String: AnyObject]
            view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[pageController]|", options: [], metrics: nil, views: views))
            view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[pageController]|", options: [], metrics: nil, views: views))
    
    for _ in realm.objects(Cities.self) {

        let mainScreenViewController = MainScrenenViewController(viewModel: self.viewModel, locationViewModel: self.locationViewModel)
        
        self.controllers.append(mainScreenViewController)
    }
    
    pageController.setViewControllers([controllers[0]], direction: .forward, animated: false)
    
    setupPageControl()

}

func setupPageControl() {
    
    let realmCities = realm.objects(Cities.self)
    
    pageControl = UIPageControl(frame: CGRect(x: 0,y: 100,width: UIScreen.main.bounds.width,height: 50))
    pageControl.numberOfPages = realmCities.count
    pageControl.tintColor = UIColor.lightGray
    pageControl.pageIndicatorTintColor = UIColor.lightGray
    pageControl.currentPageIndicatorTintColor = UIColor.black
    pageControl.backgroundColor = UIColor.clear
    view.addSubview(pageControl)
   
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

        if let index = controllers.firstIndex(of: viewController) {
            if index > 0 {
                let mainScreenViewController = MainScrenenViewController(viewModel: self.viewModel, locationViewModel: self.locationViewModel)
                
                mainScreenViewController.currentIndex -= 1
                
                controllers.append(mainScreenViewController)
                
                return controllers[index - 1]
            } else {
                return nil
            }
        }
    return nil
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController) {
            if index < controllers.count - 1 {
             
            let mainScreenViewController = MainScrenenViewController(viewModel: self.viewModel, locationViewModel: self.locationViewModel)
                
            mainScreenViewController.currentIndex  = 1
                
            controllers.append(mainScreenViewController)
                
            return controllers[index   1]
            } else {
                return nil
            }
        }
        return nil
}

MainScreenViewController

class MainScrenenViewController: UIViewController, ChangeWeatherDelegate {

let viewModel: GeneralViewModel

let locationViewModel: LocationViewModel

var currentIndex = 0 {
    didSet {
        mainCollectionView.reloadData()
        todayCollectionView.reloadData()
        weekCollectionView.reloadData()
    }
}

//MARK: -Realm
let realm = try! Realm()

CodePudding user response:

In viewDidLoad() in PageViewController, you are doing this:

for _ in realm.objects(Cities.self) {

    let mainScreenViewController = MainScrenenViewController(viewModel: self.viewModel, locationViewModel: self.locationViewModel)
    
    self.controllers.append(mainScreenViewController)
}

so, you've created an array of 8 MainScreenViewController objects.

However, you haven't set .currentIndex on them, so they currently are all currentIndex = 0.

Then, in viewControllerBefore and viewControllerAfter, instead of getting the already created view controller from your controllers array, you are *creating another instance of MainScreenViewController and setting its .currentIndex to either -= 1 or = 1 ... but then you're appending it to controllers.

Your code then returns a controller at index - 1 or index 1 from the controllers array.

It may help if you start a bit simpler... get your UIPageViewController working... and then add in the code for your view and location models.

Here's a quick example - based on your code - that adds a centered label. showing the "index" of each page:

class MainScrenenViewController: UIViewController {
    
    var currentIndex: Int = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .yellow
        
        let label = UILabel()
        label.text = "\(currentIndex)"
        label.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(label)
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }
}

class PageViewController: UIViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
    
    var pageControl = UIPageControl.appearance()
    
    var pageController: UIPageViewController!
    
    var controllers = [UIViewController]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        pageController = UIPageViewController(transitionStyle: .scroll,
                                              navigationOrientation: .horizontal,
                                              options: nil)
        pageController.delegate = self
        pageController.dataSource = self
        
        addChild(pageController)
        view.addSubview(pageController.view)
        pageController.didMove(toParent: self)

        let views = ["pageController": pageController.view] as [String: AnyObject]
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[pageController]|", options: [], metrics: nil, views: views))
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[pageController]|", options: [], metrics: nil, views: views))
        
        for i in 0..<8 {
            
            let mainScreenViewController = MainScrenenViewController()
            mainScreenViewController.currentIndex = i
            self.controllers.append(mainScreenViewController)
        }
        
        pageController.setViewControllers([controllers[0]], direction: .forward, animated: false)
        
        setupPageControl()
    }
    
    func setupPageControl() {
        
        pageControl = UIPageControl(frame: CGRect(x: 0,y: 100,width: UIScreen.main.bounds.width,height: 50))
        pageControl.numberOfPages = self.controllers.count
        pageControl.tintColor = UIColor.lightGray
        pageControl.pageIndicatorTintColor = UIColor.lightGray
        pageControl.currentPageIndicatorTintColor = UIColor.black
        pageControl.backgroundColor = UIColor.clear
        view.addSubview(pageControl)
        
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        
        if let index = controllers.firstIndex(of: viewController) {
            if index > 0 {

                return controllers[index - 1]

            } else {
                return nil
            }
        }
        return nil
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController) {
            if index < controllers.count - 1 {
                
                return controllers[index   1]

            } else {
                return nil
            }
        }
        return nil
    }

}

CodePudding user response:

You have already created your view controllers in viewDidLoad then why you are again recreating them in viewControllerBefore & viewControllerAfter ?, in viewControllerBefore & viewControllerAfter you just need to access already created view controllers, I have updated you code.

class PageViewController: UIViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource
    {
        var pageControl = UIPageControl.appearance()
        var pageController: UIPageViewController!
        var controllers = [UIViewController]()
        var pendingIndex = 0
       
        override func viewDidLoad() {
            
            super.viewDidLoad()
            
            pageController = UIPageViewController(transitionStyle: .scroll,
                                                          navigationOrientation: .horizontal,
                                                          options: nil)
            pageController.delegate = self
            pageController.dataSource = self
            addChild(pageController)
            view.addSubview(pageController.view)
            
            let views = ["pageController": pageController.view] as [String: AnyObject]
                    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[pageController]|", options: [], metrics: nil, views: views))
                    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[pageController]|", options: [], metrics: nil, views: views))
            
            for index in 0 ..< 10
            {
                let mainScreenViewController = MainScrenenViewController()
                mainScreenViewController.currentIndex = index
                mainScreenViewController.view.backgroundColor = index % 2 == 0 ? UIColor.red : UIColor.blue
                self.controllers.append(mainScreenViewController)
            }
            
            pageController.setViewControllers([controllers[0]], direction: .forward, animated: false)
            
            setupPageControl()
    
        }
    
        func setupPageControl() {
                    
            pageControl = UIPageControl(frame: CGRect(x: 0,y: 100,width: UIScreen.main.bounds.width,height: 50))
            pageControl.numberOfPages = 10
            pageControl.tintColor = UIColor.lightGray
            pageControl.pageIndicatorTintColor = UIColor.lightGray
            pageControl.currentPageIndicatorTintColor = UIColor.black
            pageControl.backgroundColor = UIColor.clear
            view.addSubview(pageControl)
           
        }
    
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
        {
            guard var index = controllers.firstIndex(of: viewController) else
            {
                return nil
            }
            
            if (index == 0)
            {
                return nil
            }
            
            index -= 1
            return controllers[index]
        }
    
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?
        {
            guard var index = controllers.firstIndex(of: viewController) else
            {
                return nil
            }
            
            index  = 1
            
            if (index >= controllers.count)
            {
                return nil
            }
            
            return controllers[index]
        }
        
        func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
        {
            if completed == true
            {
                if let pageIndex = (pageViewController.viewControllers?.first as? MainScrenenViewController)?.currentIndex
                {
                    pageControl.currentPage = pageIndex
                }
            }
            
        }
    }
    
    
    class MainScrenenViewController: UIViewController/*, ChangeWeatherDelegate*/
    {
        var currentIndex = 0
        
        override func viewDidLoad() {
            super.viewDidLoad()
            loadData()
        }
        
        func loadData()
        {
            /*mainCollectionView.reloadData()
            todayCollectionView.reloadData()
            weekCollectionView.reloadData()*/
        }
    }
  • Related