从 UITabBarController 中的另一个选项卡以编程方式在 UIPageViewController 中翻页

Posted

技术标签:

【中文标题】从 UITabBarController 中的另一个选项卡以编程方式在 UIPageViewController 中翻页【英文标题】:turn page programmatically in UIPageViewController from another tab in UITabBarController 【发布时间】:2017-10-17 11:44:00 【问题描述】:

我有一个 UITabBarController 作为根视图控制器。

在这个 UITabBarController 中,我有 2 个选项卡:tabA 和 tabB。

tabA 是通用视图控制器,tabB 是带有容器视图的视图控制器,其中嵌入了 pageViewcontroller C。

现在tabA中多了一个按钮,我想实现的效果是当我点击这个按钮时,它会跳转到tabB并显示C中的第二页,每次点击按钮时都会调用函数:

func swipeToIndex(ToIndex: Int, completion: (()->Void)? = nil) 
    if self.currentPageIndex > 2 
        return
    
    if ToIndex < self.currentPageIndex 
        let toViewController = self.orderedViewControllers[ToIndex]
        self.setViewControllers([toViewController], direction: .reverse, animated: true, completion: finish in
            self.currentPageIndex = ToIndex
            completion?()
        )
    
    else if ToIndex > self.currentPageIndex 
        let toViewController = self.orderedViewControllers[ToIndex]
        self.setViewControllers([toViewController], direction: .forward, animated: true, completion: finish in
            self.currentPageIndex = ToIndex
            completion?()
        )
    

我只能在第二次点击按钮时意识到这一点。第一次,它转到 C 语言的第一页。我发现它与 viewDidLoad() 有关。当它在

之后第一次调用函数 swipeToIndex 时

self.setViewControllers([toViewController], 方向: .forward, 动画: true, 完成: finish in self.currentPageIndex = ToIndex 完成?() ) 它会调用 viewDidLoad,在里面再次设置 viewcontroller,如下所示:

if let firstViewController = orderedViewControllers.first 
        setViewControllers([firstViewController],
                           direction: .forward,
                           animated: true,
                           completion: nil)
     

我不知道第一次调用 swipeToIndex

时如何避免这种情况

【问题讨论】:

因此,如果您打开应用程序,导航到 tabB(显示页面控制器),然后导航回 tabA,按下按钮会正常工作吗? (在至少看到一次 tabB 之前按下 tabA 上的按钮将不起作用) @MaticOblak 是的,如果导航到 tabB 并返回 tabA,按下按钮将正常工作。但是我需要意识到即使没有看到tabB,点击tabA上的按钮也会起作用。 【参考方案1】:

您需要更智能地转发消息并检查视图是否已加载。

在您的页面控制器中,您应该检查是否加载了视图:

func swipeToIndex(ToIndex: Int, completion: (()->Void)? = nil) 
    guard isViewLoaded else 
        self.pageToSwipeTo = ToIndex
        return
    

所以你需要添加

var pageToSwipeTo: Int? = nil

然后在viewDidLoad最后试试

if let pageToSwipeTo = pageToSwipeTo 
    self.pageToSwipeTo = nil
    self. swipeToIndex(pageToSwipeTo)

这是假设页面视图控制器确实已经存在于您的情况中。由于您的层次结构,这实际上可能不是真的,因此您可能需要通过标签栏视图控制器转发消息...但请先尝试此过程。

【讨论】:

这真是一个绝妙的解决方案。但在调用 viewDidLoad 之前,它还再次调用了var pageToSwipeTo: Int? = nil,所以在if let pageToSwipeTo = pageToSwipeTo self.pageToSwipeTo = nil self. swipeToIndex(pageToSwipeTo) 之前调用 pageToSwipeTo 再次变为 nil pageToSwipeTo 设为全局变量或保存到 userDefaults 有意义吗? 用户默认值没有意义,但在极少数情况下(要非常小心),您为索引创建了一个静态变量,并为索引创建了一个静态方法。然后添加一个弱静态变量作为loadedController。然后在thise上做所有的理智。我希望休息是合乎逻辑的...... 我试图将var pageToSwipeTo: Int? = nil 定义为常量文件中的全局变量。它完美无缺。与你提到的方法相比,它要简单得多。你觉得这也是实现效果的好方法吗?

以上是关于从 UITabBarController 中的另一个选项卡以编程方式在 UIPageViewController 中翻页的主要内容,如果未能解决你的问题,请参考以下文章

如何从 UITabBarController 页面导航到具有 PUSH 样式的另一个视图控制器

如何以编程方式切换到 UITabBarController 中的另一个选项卡?

熊猫:从数据透视表中的另一列中减去一列

从pickerview中的另一列确定一列值

从网络中的另一台计算机访问本地 GAE SDK 服务器

从 netbeans 中的另一种形式在表中添加行