Swift: 从其他 Viewcontroller 调用 PageViewController 中的函数

Swift: Call Function in PageViewController from other Viewcontroller

我得到了一个页面ViewController,它加载了两个 "child "ViewController 以便让用户 "swipe" 通过它们。我不想要这种轻扫手势,而是希望在我的 ViewController 中有一个函数,它允许我在 PageViewController 中使用 setViewControllers。

我尝试使用协议,但即使这样也没有成功。

对于如何实现这一目标的任何帮助或建议,我将不胜感激。谢谢!

不要设置 dataSource。当它为零时,手势将不起作用。

https://developer.apple.com/reference/uikit/uipageviewcontroller

When defining a page view controller interface, you can provide the content view controllers one at a time (or two at a time, depending upon the spine position and double-sided state) or as-needed using a data source. When providing content view controllers one at a time, you use the setViewControllers(_:direction:animated:completion:) method to set the current content view controllers. To support gesture-based navigation, you must provide your view controllers using a data source object.

简单方法...删除 pageViewController 的 viewDidLoad 中的内置手势识别器:

for view in self.pageViewController!.view.subviews {
   if let subView = view as? UIScrollView {
       subView.scrollEnabled = false
   }
}

然后在下面添加你自己的手势。我现在刚好在使用双击,但你可以让它向左滑动,向右滑动很容易:

let doubleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap))
doubleTap.numberOfTapsRequired = 2
doubleTap.delaysTouchesBegan = true
self.addGestureRecognizer(doubleTap)

以及您的代码的手势功能:

func didDoubleTap(gesture: UITapGestureRecognizer) {

//... stuff

}

要从您的子视图控制器访问 setViewControllers,您需要您的子视图控制器知道它们的父 PageViewController。为此,首先制定协议(我知道您已经说过您已经尝试过协议,但请仔细阅读我的方法)。该协议将确保每个子视图控制器都有对父 PageViewController 的引用。

    protocol PageObservation: class {
        func getParentPageViewController(parentRef: PageViewController)
    }

确保您的子视图控制器遵守 PageObservation 协议。

    class Child1ViewController: UIViewController, PageObservation {
        var parentPageViewController: PageViewController!
        func getParentPageViewController(parentRef: PageViewController) {
            parentPageViewController = parentRef
        }
    }

    class Child2ViewController: UIViewController, PageObservation {
        var parentPageViewController: PageViewController!
        func getParentPageViewController(parentRef: PageViewController) {
            parentPageViewController = parentRef
        }
    }

在您的 PageViewController 中,当您创建每个子视图控制器时,将它们转换为 PageObservation 类型并传递父 PageViewController 的引用。我使用一个名为 orderViewControllers 的数组来创建我的页面。我的 UIPageViewControllerDataSource 委托方法使用它来知道要加载哪些页面,但这与本示例无关,我只是想让您知道,以防您使用不同的方式创建页面。

    class PageViewController: UIPageViewController {
        var orderedViewControllers: [UIViewController] = []


        //creating child 1
        //i am using storyboard to create the child view controllers, I have given them the identifiers Child1ViewController and Child2ViewController respectively
        let child1ViewController =  UIStoryboard(name: "Main", bundle: nil) .
        instantiateViewController(withIdentifier: "Child1ViewController")
        let child1WithParent = child1ViewController as! PageObservation
        child1WithParent.getParentPageViewController(parentRef: self)

        orderedViewControllers.append(child1ViewController)

        //creating child 2
        let child2ViewController =  UIStoryboard(name: "Main", bundle: nil) .
        instantiateViewController(withIdentifier: "Child2ViewController")
        let child2WithParent = child2ViewController as! PageObservation
        child2WithParent.getParentPageViewController(parentRef: self)

        orderedViewControllers.append(child2ViewController)
    }

现在在您的子视图控制器中,您可以访问 setViewControllers。例如,如果我想在 child1ViewController 中调用 setViewControllers,我创建了一个名为 accessSetViewControllers() 的函数,我在其中访问 setViewControllers:

    class Child1ViewController: UIViewController, PageObservation {
         var parentPageViewController: PageViewController!
        func getParentPageViewController(parentRef: PageViewController) {
            parentPageViewController = parentRef
        }

        func accessSetViewControllers() {
             parentPageViewController.setViewControllers( //do what you need )
        }
    }

附带说明一下,尽管上面的其他答案已经说过,您可以将数据源设置为您喜欢的任何值。我有时将 dataSource 设置为 nil 以防止用户在执行某些操作之前从屏幕上滑动离开,然后将 dataSource 添加回去以允许他们继续滑动。