Search code examples
iosswiftindexinguipageviewcontroller

Why won't my index reach higher than 1?


I am trying to use PageViewController to generate new ViewControllers with data based on an array of names held in UserDefaults. When the user adds a new name into the array, the PageView should generate a new page on each swipe until the index is >= than the array.count.

The problem is while there are 5 items in the Array, I am able to swipe infinitely, the index works correctly for the first two pages, but it stays at 1 on each next swipe, so it never becomes == or >= so that it will return Nil. The array seems to be correct, when printing it prints the 5 names, but for some reason it is not indexing correctly in the pageView, can anyone Identify what the issue may be?

I hope this is enough information, Manager is the class where i hold the array called coins which contains at the moment 5 names of cryptocurrencies, the idea is to be able to add a new page, appending the array, and so that the pageView will generate a new page retrieving the data from an API to load the specific data for that coin, Very similar to the way the IOS weather app works. Thank you for the help, here is the code of the pageViewController:

import UIKit

class PageViewController: UIPageViewController,
UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    //page Control dots
    var pageControl = UIPageControl()

    func configurePageControl() {
        // The total number of pages that are available is based on how
        many available colors we have.
        pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 50,width: UIScreen.main.bounds.width,height: 50))
        self.pageControl.numberOfPages = (Manager.shared.coins.count)
        self.pageControl.currentPage = 0
        self.pageControl.tintColor = UIColor.black
        self.pageControl.pageIndicatorTintColor = UIColor.gray
        self.pageControl.currentPageIndicatorTintColor = UIColor.white
        self.view.addSubview(pageControl)
    }

    // MARK: Delegate functions
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        let pageContentViewController = pageViewController.viewControllers![0]
        self.pageControl.currentPage = (viewControllers?.index(of: pageContentViewController)!)!
    }

    func viewControllerAtIndex(_ index: Int, storyboard: UIStoryboard) -> TemplateViewController? {
        if Manager.shared.coins.count == 0 || index >= Manager.shared.coins.count {
            return nil
        }
        let templateViewController = storyboard.instantiateViewController(withIdentifier: "templateController") as! TemplateViewController
        templateViewController.dataObject = Manager.shared.coins[index]
        print(Manager.shared.coins)
        return templateViewController
    }

    func indexOfViewController(_ viewController: TemplateViewController) -> Int {
        print(viewController.dataObject)
        return Manager.shared.coins.index(of: viewController.dataObject) ?? NSNotFound
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        var index = self.indexOfViewController(viewController as! TemplateViewController)
        if (index == 0) || (index == NSNotFound){
            return nil
        }
        index -= 1
        return self.viewControllerAtIndex(index, storyboard: viewController.storyboard!)

    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        var index = self.indexOfViewController(viewController as! TemplateViewController)
        if index == NSNotFound {
            return nil
        }
        index += 1
        if index == Manager.shared.coins.count {
            return nil
        }
        return self.viewControllerAtIndex(index, storyboard: viewController.storyboard!)
    }

    //List of View Controllers.

    override func viewDidLoad() {
        super.viewDidLoad()

        self.delegate = self
        configurePageControl()

        self.dataSource = self

        if let firstViewController = viewControllerAtIndex(0, storyboard: self.storyboard!){
            self.setViewControllers([firstViewController], direction: .forward, animated: true, completion: nil)
        }
    }
}

Coins:

class Manager {
    var coins = [""]
    let defaults = UserDefaults.standard
    static let shared = Manager()
    init() {
        self.coins = self.defaults.stringArray(forKey: "SavedStringArray") ?? [String]()
    }

    func addCoin(coin:String) {
        self.coins.append(coin)
        self.defaults.set(self.coins, forKey: "SavedStringArray")
        print ("coins from addCoin:")
        print (self.coins)
    }
}

and I add coins to the array from elsewhere like so:

@IBAction func goButton(_ sender: Any) {
     self.choosePerm()
    Manager.shared.coins.append(chosenCoin)
    Manager.shared.addCoin(coin: chosenCoin)
    print(Manager.shared.coins)
    print(chosenCoin)
 }

Edit: Above I've edited the way i append the array, choosePerm() gets the name of the coin after searching has been done, and chosenCoin is the coin chosen after search, it definitely is 1 name, but I am still getting it to append double each time, can you see anything In there that might be causing that? i.e. it prints

["Ethereum", "Boolberry", "Boolberry", "Bitcoin", "Bitcoin"]

Solution

  • You are appending the coin twice:

    Manager.shared.coins.append(chosenCoin) // <-- appending for the first time
    Manager.shared.addCoin(coin: chosenCoin) // <-- appending for the second time
    
    func addCoin(coin:String) {
       self.coins.append(coin) // <-- this is the second appending
    

    This kind of error can be fixed but not allowing appending from outside the Manager class:

    private(set) var coins = [""]