UIPageViewController 不调用委托方法(Swift 5)

Posted

技术标签:

【中文标题】UIPageViewController 不调用委托方法(Swift 5)【英文标题】:UIPageViewController not calling delegate methods (Swift 5) 【发布时间】:2020-02-19 19:29:07 【问题描述】:

我的项目中有一个非常简单的 UIPageViewController 设置。当我创建我的页面视图控制器并导航到它时,一切似乎都正常工作并且它正确加载了第一页。但是,当我尝试滑动或切换到 ViewControllers 数组中的其他页面时,我的页面控制器不会调用其委托方法来执行此操作。

这是我从父视图实例化并导航到页面视图控制器的方式:

let tutorialPageVC = TareTutorialPageViewController()
let nc = UINavigationController(rootViewController: tutorialPageVC)
nc.modalPresentationStyle = .fullScreen
nc.definesPresentationContext = true
nc.setNavigationBarHidden(true, animated: true)
self.present(nc, animated: true, completion: nil)

这是我的页面视图控制器类:

import UIKit

class TareTutorialPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate 

    var tutorialPages = [UIViewController]()
    let pageControl = UIPageControl()

    override init(transitionStyle style: UIPageViewController.TransitionStyle, navigationOrientation: UIPageViewController.NavigationOrientation, options: [UIPageViewController.OptionsKey : Any]? = nil) 
        super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [:])

        self.dataSource = self
        self.delegate = self
    

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

    override func viewDidLoad() 
        super.viewDidLoad()

        let initialTutorialPage = 0

        let tutorialPage1 = TutorialPage1ViewController()
        let tutorialPage2 = TutorialPage2ViewController()
        let tutorialPage3 = TutorialPage3ViewController()

        self.tutorialPages.append(tutorialPage1)
        self.tutorialPages.append(tutorialPage2)
        self.tutorialPages.append(tutorialPage3)

        setViewControllers([tutorialPages[initialTutorialPage]], direction: .forward, animated: true, completion: nil)

        self.pageControl.frame = CGRect()
        self.pageControl.currentPageIndicatorTintColor = UIColor.white
        self.pageControl.pageIndicatorTintColor = UIColor.lightGray
        self.pageControl.numberOfPages = self.tutorialPages.count
        self.pageControl.currentPage = initialTutorialPage
        self.view.addSubview(self.pageControl)

        self.pageControl.translatesAutoresizingMaskIntoConstraints = false
        self.pageControl.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -5).isActive = true
        self.pageControl.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: -20).isActive = true
        self.pageControl.heightAnchor.constraint(equalTo: self.view.heightAnchor, constant: 20).isActive = true
        self.pageControl.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    

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

        //Might not need any of this if we only want the user to move forward??
        if let viewControllerIndex = self.tutorialPages.firstIndex(of: viewController)
        
            if viewControllerIndex == 0
            
                return self.tutorialPages.last
            
            else
            
                return self.tutorialPages[viewControllerIndex-1]
            
        

        return nil
    

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

        if let viewControllerIndex = self.tutorialPages.firstIndex(of: viewController)
        
            if viewControllerIndex < self.tutorialPages.count - 1
            
                return self.tutorialPages[viewControllerIndex + 1]
            
            else
            
                //Navigation to go to scale tare settings here...
                //For now just returns to first page of page view

                return self.tutorialPages.first
            
        

        return nil
    

    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) 

        if let viewControllers = pageViewController.viewControllers 
            if let viewControllerIndex = self.tutorialPages.firstIndex(of: viewControllers[0])
            
                self.pageControl.currentPage = viewControllerIndex
            
        
    



这是一个非常简单的视图控制器示例,由页面视图控制器显示:

import UIKit

class TutorialPage1ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()

        self.view.backgroundColor = UIColor.black

        let label = UILabel()
        label.text = "Tutorial page 1"
        label.textColor = UIColor.white
        self.view.addSubview(label)
        label.translatesAutoresizingMaskIntoConstraints = false
        label.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
        label.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 20).isActive = true
    

【问题讨论】:

【参考方案1】:

问题不在于没有调用委托函数,问题在于您完全用UIPageControl 覆盖了UIPageViewController

您可以通过添加此行来确认这一点:

   // existing line
   self.view.addSubview(self.pageControl)

   // add this line
   self.pageControl.backgroundColor = .orange

像这样改变你的约束设置:

    // completely remove these lines
    //self.pageControl.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -5).isActive = true
    //self.pageControl.widthAnchor.constraint(equalTo: self.view.widthAnchor, constant: -20).isActive = true
    //self.pageControl.heightAnchor.constraint(equalTo: self.view.heightAnchor, constant: 20).isActive = true
    //self.pageControl.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true

    let g = view.safeAreaLayoutGuide

    NSLayoutConstraint.activate([
        pageControl.widthAnchor.constraint(equalTo: g.widthAnchor, constant: -20.0),
        pageControl.centerXAnchor.constraint(equalTo: g.centerXAnchor),
        pageControl.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -5.0),
    ])

现在您应该会在底部看到页面控件,并且可以滑动浏览页面。

顺便说一句,UIPageViewController 有一个“内置”UIPageControl,你可能会发现它的效果更好。

【讨论】:

我感觉这只是对我不理解的事情的疏忽!几周前刚开始我的第一份开发工作,并参加了为期一周的 Swift 速成课程,完全没有涉及到编程限制。您的解决方案效果很好,谢谢!!

以上是关于UIPageViewController 不调用委托方法(Swift 5)的主要内容,如果未能解决你的问题,请参考以下文章

UIPageViewController -presentationCount 不触发

ViewDidLoad 不断在 UIPageViewController 上被调用

UIPageviewController 使用 Storyboard 崩溃

viewWillAppear 没有在 UIPageViewController 孩子上被调用

UIPageViewController 乱序显示页面,从不调用 viewControllerBeforeViewController

UIPageViewController 手势正在调用 viewControllerAfter: 但没有动画