Search code examples
swifttimeruipageviewcontroller

UIpageViewController And Timer


i have a UIPageViewController in one of My UICollectionViewCell at the top of my screen(height = frame.height/3) it contains a number of images and it is working good but i need it to be scrolled to the next image automattically every 3 seconds what should i do?

import UIKit

class PageViewController: UIPageViewController , UIPageViewControllerDataSource{

    var scrollingTimer = Timer()
    let imageNames = ["Apple_Watch_Main" , "Pic2" , "Pic3"]

    override func viewDidLoad() {
        super.viewDidLoad()

        dataSource = self
        let frameViewController = FrameViewController()
        frameViewController.imageName = imageNames.first

        let viewControllers = [frameViewController]
        setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)

    }

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

        let currentImageName = (viewController as! FrameViewController).imageName
        let currentIndex = imageNames.index(of: currentImageName!)
        if currentIndex! > 0 {
            let frameViewController = FrameViewController()
            frameViewController.imageName = imageNames[currentIndex! - 1]
            return frameViewController
        }
        return nil
    }

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

        let currentImageName = (viewController as! FrameViewController).imageName
        let currentIndex = imageNames.index(of: currentImageName!)
        if currentIndex! < imageNames.count - 1 {
            let frameViewController = FrameViewController()
            frameViewController.imageName = imageNames[currentIndex! + 1]
            return frameViewController
        }
        return nil
    }
}

and i added to my cell here

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        switch indexPath.item {
        case 0 :
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as!ImageCell

            let pagecontroller = PageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
            self.addChildViewController(pagecontroller)

            cell.addSubview(pagecontroller.view)

            pagecontroller.view.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height/3)
            return cell
        case 1 :
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "filterandorganize", for: indexPath) as! FilterAndOrganize
            return cell
        case 2 :
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Offers", for: indexPath) as! Offers
            return cell
        case 3 :
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OfferedProducts", for: indexPath) as! OfferedProducts
            cell.firstViewController = self
            return cell
        default:
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Offers", for: indexPath) as! Offers
            return cell
        }
    }

in case 0

I searched a lot and i found some questions like this but without any complete and correct answer

HERE IS THE ANSWER I FOUND but it still have one bug and that is when the user swipes it self the autoscroll is not perfect and maybe jump of one pic to another

class PageViewController: UIPageViewController , UIPageViewControllerDataSource{
    var index = 0
    let imageNames = ["Apple_Watch_Main" , "Pic2" , "Pic3"]

    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = self

        let frameViewController = FrameViewController()
        frameViewController.imageName = imageNames[index]
        index += 1
        let viewControllers = [frameViewController]
        setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)

        Timer.scheduledTimer(timeInterval: 6.0 ,
                             target: self,
                             selector: #selector(myFunc(_:)),
                             userInfo: index,
                             repeats: true)
    }
    //FIXME: needs some fixes
    func myFunc(_ timer: Timer) {
        if index == imageNames.count  {
            index = 0
        }
        else {
            self.changePIC(index)
            index += 1
        }
    }
    func changePIC(_ i: Int) {
        let frameViewController = FrameViewController()
        frameViewController.imageName = imageNames[i]
        let viewControllers = [frameViewController]
        setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)
    }

Solution

  • First crate a Timer with timeInterval and option repeats seat to true.

    Example:

    Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(scrollToNextItem), userInfo: nil, repeats: true)

    Now you have Timer that will trigger scrollToNextItem method every 3 seconds.

    Now read about setViewControllers(_:direction:animated:completion:) to know how to set view controllers to be displayed.

    Than implement scrollToNextItem method with required logic.