Ios 如何修复UIPageViewController手动分页?

Ios 如何修复UIPageViewController手动分页?,ios,swift,xcode,uipageviewcontroller,uipagecontrol,Ios,Swift,Xcode,Uipageviewcontroller,Uipagecontrol,UIPageViewController手动分页工作不正常 自动分页工作正常,但当我们手动旋转时,它不能正常工作 我的视图控制器.Swift代码 import UIKit class ViewController: UIViewController { @IBOutlet weak var contentView: UIView! @IBOutlet weak var pageControl: UIPageControl! let myDataSource = [&q

UIPageViewController手动分页工作不正常

自动分页工作正常,但当我们手动旋转时,它不能正常工作

我的视图控制器.Swift代码

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!
    let myDataSource = ["Img1", "Img2", "Img3", "Img4"]
    let urlDataSource = ["https://fabric.io/", "https://about.gitlab.com/", "https://developer.apple.com/", "https://fast.com/"]
    var currentVCIndex = 0
    var timer = Timer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        configurePageViewController()
        timerStart()
    }

    func timerStart() {
        timer.invalidate()
        timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(configurePageViewController), userInfo: nil, repeats: true)
    }
    
    @objc func configurePageViewController() {
        guard let pageVc = storyboard?.instantiateViewController(identifier: "CustomPageViewController") as? CustomPageViewController else {
            return
        }
        
        pageVc.delegate = self
        pageVc.dataSource = self
        
        addChild(pageVc)
        pageVc.didMove(toParent: self)
        
        pageVc.view.translatesAutoresizingMaskIntoConstraints = false
                        
        pageControl.layer.zPosition = 1;
        pageControl.numberOfPages = myDataSource.count
        pageControl.currentPageIndicatorTintColor = .lightGray
        pageControl.pageIndicatorTintColor = .white
        
        contentView.addSubview(pageVc.view)
        
        let views : [String : Any] = ["pageView": pageVc.view!]
        
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[pageView]-0-|",
                                                                  options: NSLayoutConstraint.FormatOptions(rawValue: 0),
                                                                  metrics: nil,
                                                                  views: views))
        
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[pageView]-0-|",
                                                                  options: NSLayoutConstraint.FormatOptions(rawValue: 0),
                                                                  metrics: nil,
                                                                  views: views))
        guard let startingVc = detailVCAt(index: currentVCIndex) else {
            return
        }
        
        pageVc.setViewControllers([startingVc], direction: .forward, animated: true)

        increaseCount()
    }
    
    func increaseCount() {
        pageControl.currentPage = currentVCIndex
        
        if currentVCIndex == 3 {
            currentVCIndex = 0
        } else {
            currentVCIndex = currentVCIndex+1
        }
    }
    
    func detailVCAt(index: Int) -> DataViewController? {
        
        if index >= myDataSource.count || myDataSource.count == 0 {
            return nil
        }
        
        guard let dataVC = storyboard?.instantiateViewController(identifier: "DataViewController") as? DataViewController else {
            return nil
        }
        
        dataVC.index = index
        dataVC.displayImgName = myDataSource[index]
        dataVC.redirectURL = urlDataSource[index]
        
        return dataVC
    }

}

extension ViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
    
    func presentationIndex(for _: UIPageViewController) -> Int {
        return myDataSource.count
    }
    
    func presentationCount(for _: UIPageViewController) -> Int {
        return myDataSource.count
    }
    
    func pageViewController(_: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        
        let dataVc = viewController as? DataViewController
        
        guard var currentIndex = dataVc?.index else {
            return nil
        }

        currentVCIndex = currentIndex
        
        if currentIndex == 0 {
            return nil
        }

        currentIndex -= 1
        pageControl.currentPage = currentVCIndex
    //        timerStart()
    //        increaseCount()
        return detailVCAt(index: currentIndex)
    }
    
    func pageViewController(_: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        
        let dataVc = viewController as? DataViewController
        
        guard var currentIndex = dataVc?.index else {
            return nil
        }

        if currentIndex == myDataSource.count {
            return nil
        }
        
        currentIndex += 1

        currentVCIndex = currentIndex
        pageControl.currentPage = currentVCIndex
    //        timerStart()
    //        increaseCount()
        return detailVCAt(index: currentIndex)
    }
    
    
}
import UIKit

class DataViewController: UIViewController {
    
    @IBOutlet weak var btn: UIButton!
    var displayImgName :String?
    var redirectURL :String?
    var index: Int?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        btn.setImage(UIImage.init(named: displayImgName ?? ""), for: .normal)
    }
    
    @IBAction func onClickBtn(_ sender: UIButton) {
        
        if let url = URL(string: redirectURL ?? ""), UIApplication.shared.canOpenURL(url) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(url)
            }
        }
    }
    
}
import UIKit

class CustomPageViewController: UIPageViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
       
}
MyDataViewController.Swift代码

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!
    let myDataSource = ["Img1", "Img2", "Img3", "Img4"]
    let urlDataSource = ["https://fabric.io/", "https://about.gitlab.com/", "https://developer.apple.com/", "https://fast.com/"]
    var currentVCIndex = 0
    var timer = Timer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        configurePageViewController()
        timerStart()
    }

    func timerStart() {
        timer.invalidate()
        timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(configurePageViewController), userInfo: nil, repeats: true)
    }
    
    @objc func configurePageViewController() {
        guard let pageVc = storyboard?.instantiateViewController(identifier: "CustomPageViewController") as? CustomPageViewController else {
            return
        }
        
        pageVc.delegate = self
        pageVc.dataSource = self
        
        addChild(pageVc)
        pageVc.didMove(toParent: self)
        
        pageVc.view.translatesAutoresizingMaskIntoConstraints = false
                        
        pageControl.layer.zPosition = 1;
        pageControl.numberOfPages = myDataSource.count
        pageControl.currentPageIndicatorTintColor = .lightGray
        pageControl.pageIndicatorTintColor = .white
        
        contentView.addSubview(pageVc.view)
        
        let views : [String : Any] = ["pageView": pageVc.view!]
        
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[pageView]-0-|",
                                                                  options: NSLayoutConstraint.FormatOptions(rawValue: 0),
                                                                  metrics: nil,
                                                                  views: views))
        
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[pageView]-0-|",
                                                                  options: NSLayoutConstraint.FormatOptions(rawValue: 0),
                                                                  metrics: nil,
                                                                  views: views))
        guard let startingVc = detailVCAt(index: currentVCIndex) else {
            return
        }
        
        pageVc.setViewControllers([startingVc], direction: .forward, animated: true)

        increaseCount()
    }
    
    func increaseCount() {
        pageControl.currentPage = currentVCIndex
        
        if currentVCIndex == 3 {
            currentVCIndex = 0
        } else {
            currentVCIndex = currentVCIndex+1
        }
    }
    
    func detailVCAt(index: Int) -> DataViewController? {
        
        if index >= myDataSource.count || myDataSource.count == 0 {
            return nil
        }
        
        guard let dataVC = storyboard?.instantiateViewController(identifier: "DataViewController") as? DataViewController else {
            return nil
        }
        
        dataVC.index = index
        dataVC.displayImgName = myDataSource[index]
        dataVC.redirectURL = urlDataSource[index]
        
        return dataVC
    }

}

extension ViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
    
    func presentationIndex(for _: UIPageViewController) -> Int {
        return myDataSource.count
    }
    
    func presentationCount(for _: UIPageViewController) -> Int {
        return myDataSource.count
    }
    
    func pageViewController(_: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        
        let dataVc = viewController as? DataViewController
        
        guard var currentIndex = dataVc?.index else {
            return nil
        }

        currentVCIndex = currentIndex
        
        if currentIndex == 0 {
            return nil
        }

        currentIndex -= 1
        pageControl.currentPage = currentVCIndex
    //        timerStart()
    //        increaseCount()
        return detailVCAt(index: currentIndex)
    }
    
    func pageViewController(_: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        
        let dataVc = viewController as? DataViewController
        
        guard var currentIndex = dataVc?.index else {
            return nil
        }

        if currentIndex == myDataSource.count {
            return nil
        }
        
        currentIndex += 1

        currentVCIndex = currentIndex
        pageControl.currentPage = currentVCIndex
    //        timerStart()
    //        increaseCount()
        return detailVCAt(index: currentIndex)
    }
    
    
}
import UIKit

class DataViewController: UIViewController {
    
    @IBOutlet weak var btn: UIButton!
    var displayImgName :String?
    var redirectURL :String?
    var index: Int?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        btn.setImage(UIImage.init(named: displayImgName ?? ""), for: .normal)
    }
    
    @IBAction func onClickBtn(_ sender: UIButton) {
        
        if let url = URL(string: redirectURL ?? ""), UIApplication.shared.canOpenURL(url) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(url)
            }
        }
    }
    
}
import UIKit

class CustomPageViewController: UIPageViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
       
}
MyCustomPageViewController.Swift代码

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!
    let myDataSource = ["Img1", "Img2", "Img3", "Img4"]
    let urlDataSource = ["https://fabric.io/", "https://about.gitlab.com/", "https://developer.apple.com/", "https://fast.com/"]
    var currentVCIndex = 0
    var timer = Timer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        configurePageViewController()
        timerStart()
    }

    func timerStart() {
        timer.invalidate()
        timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(configurePageViewController), userInfo: nil, repeats: true)
    }
    
    @objc func configurePageViewController() {
        guard let pageVc = storyboard?.instantiateViewController(identifier: "CustomPageViewController") as? CustomPageViewController else {
            return
        }
        
        pageVc.delegate = self
        pageVc.dataSource = self
        
        addChild(pageVc)
        pageVc.didMove(toParent: self)
        
        pageVc.view.translatesAutoresizingMaskIntoConstraints = false
                        
        pageControl.layer.zPosition = 1;
        pageControl.numberOfPages = myDataSource.count
        pageControl.currentPageIndicatorTintColor = .lightGray
        pageControl.pageIndicatorTintColor = .white
        
        contentView.addSubview(pageVc.view)
        
        let views : [String : Any] = ["pageView": pageVc.view!]
        
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[pageView]-0-|",
                                                                  options: NSLayoutConstraint.FormatOptions(rawValue: 0),
                                                                  metrics: nil,
                                                                  views: views))
        
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[pageView]-0-|",
                                                                  options: NSLayoutConstraint.FormatOptions(rawValue: 0),
                                                                  metrics: nil,
                                                                  views: views))
        guard let startingVc = detailVCAt(index: currentVCIndex) else {
            return
        }
        
        pageVc.setViewControllers([startingVc], direction: .forward, animated: true)

        increaseCount()
    }
    
    func increaseCount() {
        pageControl.currentPage = currentVCIndex
        
        if currentVCIndex == 3 {
            currentVCIndex = 0
        } else {
            currentVCIndex = currentVCIndex+1
        }
    }
    
    func detailVCAt(index: Int) -> DataViewController? {
        
        if index >= myDataSource.count || myDataSource.count == 0 {
            return nil
        }
        
        guard let dataVC = storyboard?.instantiateViewController(identifier: "DataViewController") as? DataViewController else {
            return nil
        }
        
        dataVC.index = index
        dataVC.displayImgName = myDataSource[index]
        dataVC.redirectURL = urlDataSource[index]
        
        return dataVC
    }

}

extension ViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
    
    func presentationIndex(for _: UIPageViewController) -> Int {
        return myDataSource.count
    }
    
    func presentationCount(for _: UIPageViewController) -> Int {
        return myDataSource.count
    }
    
    func pageViewController(_: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        
        let dataVc = viewController as? DataViewController
        
        guard var currentIndex = dataVc?.index else {
            return nil
        }

        currentVCIndex = currentIndex
        
        if currentIndex == 0 {
            return nil
        }

        currentIndex -= 1
        pageControl.currentPage = currentVCIndex
    //        timerStart()
    //        increaseCount()
        return detailVCAt(index: currentIndex)
    }
    
    func pageViewController(_: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        
        let dataVc = viewController as? DataViewController
        
        guard var currentIndex = dataVc?.index else {
            return nil
        }

        if currentIndex == myDataSource.count {
            return nil
        }
        
        currentIndex += 1

        currentVCIndex = currentIndex
        pageControl.currentPage = currentVCIndex
    //        timerStart()
    //        increaseCount()
        return detailVCAt(index: currentIndex)
    }
    
    
}
import UIKit

class DataViewController: UIViewController {
    
    @IBOutlet weak var btn: UIButton!
    var displayImgName :String?
    var redirectURL :String?
    var index: Int?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        btn.setImage(UIImage.init(named: displayImgName ?? ""), for: .normal)
    }
    
    @IBAction func onClickBtn(_ sender: UIButton) {
        
        if let url = URL(string: redirectURL ?? ""), UIApplication.shared.canOpenURL(url) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(url)
            }
        }
    }
    
}
import UIKit

class CustomPageViewController: UIPageViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
       
}
我的故事板图像


在您的代码中,
currentIndex
出错了。您可以使用以下委托方法获得正确的
currentIndex

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
另外,在计划的计时器
configurePageViewController
方法中,每5秒调用一次。此方法在调用方法时创建
UIPageViewController
的新实例,并添加子视图,这将在将来导致内存问题

我建议您使用故事板在ContainerView中添加
UIPageViewController
。你可以找到附加的截图

对于您的场景,我有一个更好的解决方案。请查找以下代码:

MyViewController.Swift代码:

class ViewController: UIViewController {
    
    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!
    let myDataSource = ["Img1", "Img2", "Img3", "Img4"]
    let urlDataSource = ["https://fabric.io/", "https://about.gitlab.com/", "https://developer.apple.com/", "https://fast.com/"]
    var timer = Timer()
    var pageViewController: CustomPageViewController? {
        didSet {
            pageViewController?.objViewController = self
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configurePageControl()
        timerStart()
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let pageViewController = segue.destination as? CustomPageViewController {
            self.pageViewController = pageViewController
        }
    }
    
    func pageViewIdexChange(_ index : Int) {
        pageControl.currentPage = index
    }
    
    func timerStart() {
        timer.invalidate()
        guard let pageViewController = pageViewController else { return }
        timer = Timer.scheduledTimer(timeInterval: 5.0, target: pageViewController, selector: #selector(pageViewController.scrollToNextViewController), userInfo: nil, repeats: true)
    }

    func configurePageControl() {
        pageControl.numberOfPages = myDataSource.count
        pageControl.currentPageIndicatorTintColor = .lightGray
        pageControl.pageIndicatorTintColor = .white
    }
    
}
class DataViewController: UIViewController {
    
    @IBOutlet weak var btn: UIButton!
    var displayImgName :String?
    var redirectURL :String?
    var index: Int?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        btn.setImage(UIImage.init(named: displayImgName ?? ""), for: .normal)
        view.backgroundColor = .random()
    }
    
    @IBAction func onClickBtn(_ sender: UIButton) {
        
        if let url = URL(string: redirectURL ?? ""), UIApplication.shared.canOpenURL(url) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(url)
            }
        }
    }
    
}
import UIKit

class CustomPageViewController: UIPageViewController {
    
    weak var objViewController: ViewController?
    var myDataSource: [String] = []
    var urlDataSource: [String] = []
    var currentIndex = 0
    
    private(set) lazy var orderedViewControllers: [UIViewController] = {
        // The view controllers will be shown in this order
        var vcs : [DataViewController] = []
        for i in 0 ..< myDataSource.count {
            vcs.append(detailVCAt(index: i)!)
        }
        return vcs
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = self
        delegate = self
        
        myDataSource = objViewController?.myDataSource ?? []
        urlDataSource = objViewController?.urlDataSource ?? []
        
        if let initialViewController = orderedViewControllers.first {
            scrollToViewController(initialViewController)
        }
    }
    
    func detailVCAt(index: Int) -> DataViewController? {
        
        if index >= myDataSource.count || myDataSource.count == 0 {
            return nil
        }
        
        guard let dataVC = storyboard?.instantiateViewController(identifier: "DataViewController") as? DataViewController else {
            return nil
        }
        
        dataVC.index = index
        dataVC.displayImgName = myDataSource[index]
        dataVC.redirectURL = urlDataSource[index]
        
        return dataVC
    }
    
    //MARK: - Methods
    @objc func scrollToNextViewController() {
        if currentIndex < orderedViewControllers.count - 1 {
            scrollToViewController(currentIndex + 1)
        } else {
            scrollToViewController(0, direction: .forward)
        }
    }
    
    func scrollToViewController(_ newIndex: Int, direction: UIPageViewController.NavigationDirection? = nil) {
        var direction = direction
        if let firstViewController = viewControllers?.first,
           let currentIndex = orderedViewControllers.firstIndex(of: firstViewController) {
            if direction == nil {
                direction = newIndex >= currentIndex ? .forward : .reverse
            }
            let nextViewController = orderedViewControllers[newIndex]
            scrollToViewController(nextViewController, direction: direction!)
        }
    }
    
    func scrollToViewController(_ viewController: UIViewController,
                                direction: UIPageViewController.NavigationDirection = .forward) {
        setViewControllers([viewController],
                           direction: direction,
                           animated: true,
                           completion: { (finished) -> Void in
                            // Setting the view controller programmatically does not fire
                            // any delegate methods, so we have to manually notify the
                            // 'tutorialDelegate' of the new index.
                            self.notifyTutorialDelegateOfNewIndex()
                           })
    }
    
    private func notifyTutorialDelegateOfNewIndex() {
        
        if let firstViewController = viewControllers?.first,
           let index = orderedViewControllers.firstIndex(of: firstViewController) {
            currentIndex = index
            objViewController?.pageViewIdexChange(index)
        }
    }
    
    
}

// MARK: - UIPageViewControllerDataSource & UIPageViewControllerDelegate
extension CustomPageViewController : UIPageViewControllerDataSource , UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.firstIndex(of: viewController) else {
            return nil
        }
        
        let previousIndex = viewControllerIndex - 1
        
        // User is on the first view controller and swiped left to loop to
        // the last view controller.
        guard previousIndex >= 0 else {
            return orderedViewControllers.last
        }
        
        guard orderedViewControllers.count > previousIndex else {
            return nil
        }
        
        return orderedViewControllers[previousIndex]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.firstIndex(of: viewController)  else {
            return nil
        }
        
        let nextIndex = viewControllerIndex + 1
        let orderedViewControllersCount = orderedViewControllers.count
        
        // User is on the last view controller and swiped right to loop to
        // the first view controller.
        guard orderedViewControllersCount != nextIndex else {
            return orderedViewControllers.first
        }
        
        guard orderedViewControllersCount > nextIndex else {
            return nil
        }
        
        return orderedViewControllers[nextIndex]
    }
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        
        notifyTutorialDelegateOfNewIndex()
    }
    
}
MyDataViewController.Swift代码:

class ViewController: UIViewController {
    
    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!
    let myDataSource = ["Img1", "Img2", "Img3", "Img4"]
    let urlDataSource = ["https://fabric.io/", "https://about.gitlab.com/", "https://developer.apple.com/", "https://fast.com/"]
    var timer = Timer()
    var pageViewController: CustomPageViewController? {
        didSet {
            pageViewController?.objViewController = self
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configurePageControl()
        timerStart()
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let pageViewController = segue.destination as? CustomPageViewController {
            self.pageViewController = pageViewController
        }
    }
    
    func pageViewIdexChange(_ index : Int) {
        pageControl.currentPage = index
    }
    
    func timerStart() {
        timer.invalidate()
        guard let pageViewController = pageViewController else { return }
        timer = Timer.scheduledTimer(timeInterval: 5.0, target: pageViewController, selector: #selector(pageViewController.scrollToNextViewController), userInfo: nil, repeats: true)
    }

    func configurePageControl() {
        pageControl.numberOfPages = myDataSource.count
        pageControl.currentPageIndicatorTintColor = .lightGray
        pageControl.pageIndicatorTintColor = .white
    }
    
}
class DataViewController: UIViewController {
    
    @IBOutlet weak var btn: UIButton!
    var displayImgName :String?
    var redirectURL :String?
    var index: Int?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        btn.setImage(UIImage.init(named: displayImgName ?? ""), for: .normal)
        view.backgroundColor = .random()
    }
    
    @IBAction func onClickBtn(_ sender: UIButton) {
        
        if let url = URL(string: redirectURL ?? ""), UIApplication.shared.canOpenURL(url) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(url)
            }
        }
    }
    
}
import UIKit

class CustomPageViewController: UIPageViewController {
    
    weak var objViewController: ViewController?
    var myDataSource: [String] = []
    var urlDataSource: [String] = []
    var currentIndex = 0
    
    private(set) lazy var orderedViewControllers: [UIViewController] = {
        // The view controllers will be shown in this order
        var vcs : [DataViewController] = []
        for i in 0 ..< myDataSource.count {
            vcs.append(detailVCAt(index: i)!)
        }
        return vcs
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = self
        delegate = self
        
        myDataSource = objViewController?.myDataSource ?? []
        urlDataSource = objViewController?.urlDataSource ?? []
        
        if let initialViewController = orderedViewControllers.first {
            scrollToViewController(initialViewController)
        }
    }
    
    func detailVCAt(index: Int) -> DataViewController? {
        
        if index >= myDataSource.count || myDataSource.count == 0 {
            return nil
        }
        
        guard let dataVC = storyboard?.instantiateViewController(identifier: "DataViewController") as? DataViewController else {
            return nil
        }
        
        dataVC.index = index
        dataVC.displayImgName = myDataSource[index]
        dataVC.redirectURL = urlDataSource[index]
        
        return dataVC
    }
    
    //MARK: - Methods
    @objc func scrollToNextViewController() {
        if currentIndex < orderedViewControllers.count - 1 {
            scrollToViewController(currentIndex + 1)
        } else {
            scrollToViewController(0, direction: .forward)
        }
    }
    
    func scrollToViewController(_ newIndex: Int, direction: UIPageViewController.NavigationDirection? = nil) {
        var direction = direction
        if let firstViewController = viewControllers?.first,
           let currentIndex = orderedViewControllers.firstIndex(of: firstViewController) {
            if direction == nil {
                direction = newIndex >= currentIndex ? .forward : .reverse
            }
            let nextViewController = orderedViewControllers[newIndex]
            scrollToViewController(nextViewController, direction: direction!)
        }
    }
    
    func scrollToViewController(_ viewController: UIViewController,
                                direction: UIPageViewController.NavigationDirection = .forward) {
        setViewControllers([viewController],
                           direction: direction,
                           animated: true,
                           completion: { (finished) -> Void in
                            // Setting the view controller programmatically does not fire
                            // any delegate methods, so we have to manually notify the
                            // 'tutorialDelegate' of the new index.
                            self.notifyTutorialDelegateOfNewIndex()
                           })
    }
    
    private func notifyTutorialDelegateOfNewIndex() {
        
        if let firstViewController = viewControllers?.first,
           let index = orderedViewControllers.firstIndex(of: firstViewController) {
            currentIndex = index
            objViewController?.pageViewIdexChange(index)
        }
    }
    
    
}

// MARK: - UIPageViewControllerDataSource & UIPageViewControllerDelegate
extension CustomPageViewController : UIPageViewControllerDataSource , UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.firstIndex(of: viewController) else {
            return nil
        }
        
        let previousIndex = viewControllerIndex - 1
        
        // User is on the first view controller and swiped left to loop to
        // the last view controller.
        guard previousIndex >= 0 else {
            return orderedViewControllers.last
        }
        
        guard orderedViewControllers.count > previousIndex else {
            return nil
        }
        
        return orderedViewControllers[previousIndex]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.firstIndex(of: viewController)  else {
            return nil
        }
        
        let nextIndex = viewControllerIndex + 1
        let orderedViewControllersCount = orderedViewControllers.count
        
        // User is on the last view controller and swiped right to loop to
        // the first view controller.
        guard orderedViewControllersCount != nextIndex else {
            return orderedViewControllers.first
        }
        
        guard orderedViewControllersCount > nextIndex else {
            return nil
        }
        
        return orderedViewControllers[nextIndex]
    }
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        
        notifyTutorialDelegateOfNewIndex()
    }
    
}
MyCustomPageViewController.Swift代码:

class ViewController: UIViewController {
    
    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!
    let myDataSource = ["Img1", "Img2", "Img3", "Img4"]
    let urlDataSource = ["https://fabric.io/", "https://about.gitlab.com/", "https://developer.apple.com/", "https://fast.com/"]
    var timer = Timer()
    var pageViewController: CustomPageViewController? {
        didSet {
            pageViewController?.objViewController = self
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configurePageControl()
        timerStart()
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let pageViewController = segue.destination as? CustomPageViewController {
            self.pageViewController = pageViewController
        }
    }
    
    func pageViewIdexChange(_ index : Int) {
        pageControl.currentPage = index
    }
    
    func timerStart() {
        timer.invalidate()
        guard let pageViewController = pageViewController else { return }
        timer = Timer.scheduledTimer(timeInterval: 5.0, target: pageViewController, selector: #selector(pageViewController.scrollToNextViewController), userInfo: nil, repeats: true)
    }

    func configurePageControl() {
        pageControl.numberOfPages = myDataSource.count
        pageControl.currentPageIndicatorTintColor = .lightGray
        pageControl.pageIndicatorTintColor = .white
    }
    
}
class DataViewController: UIViewController {
    
    @IBOutlet weak var btn: UIButton!
    var displayImgName :String?
    var redirectURL :String?
    var index: Int?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        btn.setImage(UIImage.init(named: displayImgName ?? ""), for: .normal)
        view.backgroundColor = .random()
    }
    
    @IBAction func onClickBtn(_ sender: UIButton) {
        
        if let url = URL(string: redirectURL ?? ""), UIApplication.shared.canOpenURL(url) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(url)
            }
        }
    }
    
}
import UIKit

class CustomPageViewController: UIPageViewController {
    
    weak var objViewController: ViewController?
    var myDataSource: [String] = []
    var urlDataSource: [String] = []
    var currentIndex = 0
    
    private(set) lazy var orderedViewControllers: [UIViewController] = {
        // The view controllers will be shown in this order
        var vcs : [DataViewController] = []
        for i in 0 ..< myDataSource.count {
            vcs.append(detailVCAt(index: i)!)
        }
        return vcs
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = self
        delegate = self
        
        myDataSource = objViewController?.myDataSource ?? []
        urlDataSource = objViewController?.urlDataSource ?? []
        
        if let initialViewController = orderedViewControllers.first {
            scrollToViewController(initialViewController)
        }
    }
    
    func detailVCAt(index: Int) -> DataViewController? {
        
        if index >= myDataSource.count || myDataSource.count == 0 {
            return nil
        }
        
        guard let dataVC = storyboard?.instantiateViewController(identifier: "DataViewController") as? DataViewController else {
            return nil
        }
        
        dataVC.index = index
        dataVC.displayImgName = myDataSource[index]
        dataVC.redirectURL = urlDataSource[index]
        
        return dataVC
    }
    
    //MARK: - Methods
    @objc func scrollToNextViewController() {
        if currentIndex < orderedViewControllers.count - 1 {
            scrollToViewController(currentIndex + 1)
        } else {
            scrollToViewController(0, direction: .forward)
        }
    }
    
    func scrollToViewController(_ newIndex: Int, direction: UIPageViewController.NavigationDirection? = nil) {
        var direction = direction
        if let firstViewController = viewControllers?.first,
           let currentIndex = orderedViewControllers.firstIndex(of: firstViewController) {
            if direction == nil {
                direction = newIndex >= currentIndex ? .forward : .reverse
            }
            let nextViewController = orderedViewControllers[newIndex]
            scrollToViewController(nextViewController, direction: direction!)
        }
    }
    
    func scrollToViewController(_ viewController: UIViewController,
                                direction: UIPageViewController.NavigationDirection = .forward) {
        setViewControllers([viewController],
                           direction: direction,
                           animated: true,
                           completion: { (finished) -> Void in
                            // Setting the view controller programmatically does not fire
                            // any delegate methods, so we have to manually notify the
                            // 'tutorialDelegate' of the new index.
                            self.notifyTutorialDelegateOfNewIndex()
                           })
    }
    
    private func notifyTutorialDelegateOfNewIndex() {
        
        if let firstViewController = viewControllers?.first,
           let index = orderedViewControllers.firstIndex(of: firstViewController) {
            currentIndex = index
            objViewController?.pageViewIdexChange(index)
        }
    }
    
    
}

// MARK: - UIPageViewControllerDataSource & UIPageViewControllerDelegate
extension CustomPageViewController : UIPageViewControllerDataSource , UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.firstIndex(of: viewController) else {
            return nil
        }
        
        let previousIndex = viewControllerIndex - 1
        
        // User is on the first view controller and swiped left to loop to
        // the last view controller.
        guard previousIndex >= 0 else {
            return orderedViewControllers.last
        }
        
        guard orderedViewControllers.count > previousIndex else {
            return nil
        }
        
        return orderedViewControllers[previousIndex]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.firstIndex(of: viewController)  else {
            return nil
        }
        
        let nextIndex = viewControllerIndex + 1
        let orderedViewControllersCount = orderedViewControllers.count
        
        // User is on the last view controller and swiped right to loop to
        // the first view controller.
        guard orderedViewControllersCount != nextIndex else {
            return orderedViewControllers.first
        }
        
        guard orderedViewControllersCount > nextIndex else {
            return nil
        }
        
        return orderedViewControllers[nextIndex]
    }
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        
        notifyTutorialDelegateOfNewIndex()
    }
    
}
导入UIKit
类CustomPageViewController:UIPageViewController{
弱var objViewController:ViewController?
var myDataSource:[字符串]=[]
var urlDataSource:[字符串]=[]
var currentIndex=0
私有(集)惰性变量OrderedViewController:[UIViewController]={
//视图控制器将按此顺序显示
var vcs:[DataViewController]=[]
对于0中的i..DataViewController{
如果索引>=myDataSource.count | | myDataSource.count==0{
归零
}
guard let dataVC=storyboard?。将EViewController(标识符:“DataViewController”)实例化为?DataViewController else{
归零
}
dataVC.index=索引
dataVC.displayimname=myDataSource[index]
dataVC.redirectURL=urlDataSource[index]
返回数据VC
}
//标记:-方法
@objc func scrollToNextViewController(){
如果currentIndex=当前索引?。正向:。反向
}
让nextViewController=OrderedViewController[newIndex]
scrollToViewController(下一个视图控制器,方向:方向!)
}
}
func scrollToViewController(viewController:UIViewController,
方向:UIPageViewController.NavigationDirection=.forward){
SetViewController([viewController],
方向:方向,,
是的,
完成:{(已完成)->在中无效
//以编程方式设置视图控制器不会触发
//任何委托方法,因此我们必须手动通知
//新索引的“tutorialDelegate”。
self.notifyTutorialDelegateOfNewIndex()
})
}
私有函数notifyTutorialDelegateOfNewIndex(){
如果让firstViewController=ViewController?。首先,
let index=OrderedViewController.firstIndex(of:firstViewController){
当前索引=索引
objViewController?.PageViewIdeExchange(索引)
}
}
}
//标记:-UIPageViewControllerDataSource和UIPageViewControllerDelegate
扩展CustomPageViewController:UIPageViewControllerDataSource、UIPageViewControllerDelegate{
func pageViewController(uPageViewController:UIPageViewController,viewController在viewController:UIViewController之前)->UIViewController{
guard let viewControllerIndex=orderedViewControllers.firstIndex(of:viewController)else{
归零
}
让previousIndex=viewControllerIndex-1
//用户位于第一个视图控制器上,向左滑动以循环到
//最后一个视图控制器。
guard previousIndex>=0其他{
返回orderedViewControllers.last
}
guard OrderedViewController.count>previousIndex else{
归零
}
返回orderedViewControllers[previousIndex]
}
func pageViewController(pageViewController:UIPageViewController,viewController后的viewController:UIViewController)->UIViewController{
guard let viewControllerIndex=orderedViewControllers.firstIndex(of:viewController)else{
归零
}
设nextIndex=viewControllerIndex+1
让orderedViewControllersCount=orderedViewControllers.count
//用户位于最后一个视图上