快速滚动 UIPageViewController 阻止视图控制器更新

2024-03-28

我有一个 UIPageviewcontroller,里面有两个控制器。当您滑动到下一个时,我使用 viewController 参数来设置适当的委托。但我的经验是,如果你滑动得太快,函数 viewControllerAfter 就无法正确更新 viewController。最初的滑动应该将视图控制器的索引从 0 更新为 1,但如果滑动太快则不会这样做。

import UIKit

class WizardPageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {

    lazy var orderedViewControllers: [UIViewController] = {
        return [self.newVc(viewController: "intro"),
                self.newVc(viewController: "welcome")]
    }()

    var pageControl = UIPageControl()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.dataSource = self
        self.delegate = self
        configurePageControl()

        // This sets up the first view that will show up on our page control
        if let firstViewController = orderedViewControllers.first {
            setViewControllers([firstViewController],
                               direction: .forward,
                               animated: true,
                               completion: nil)
        }
    }

    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        let pageContentViewController = pageViewController.viewControllers![0]
        self.pageControl.currentPage = orderedViewControllers.index(of: pageContentViewController)!
    }

    func newVc(viewController: String) -> UIViewController {
        return UIStoryboard(name: "Wizard", bundle: nil).instantiateViewController(withIdentifier: viewController)
    }

    func configurePageControl() {
        // The total number of pages that are available is based on how many available colors we have.
        pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 225,width: UIScreen.main.bounds.width,height: 50))
        self.pageControl.numberOfPages = orderedViewControllers.count
        self.pageControl.currentPage = 0
        pageControl.isEnabled = false
        //self.pageControl.tintColor = UIColor.black
        self.pageControl.pageIndicatorTintColor = UIColor.gray
        self.pageControl.currentPageIndicatorTintColor = UIColor(red:0.647, green:0.192, blue:0.216, alpha:1.00)
        self.view.addSubview(pageControl)
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
            return nil
        }

        print(orderedViewControllers.index(of: viewController))
        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 nil
            // Uncommment the line below, remove the line above if you don't want the page control to loop.
            // return nil
        }

        guard orderedViewControllers.count > previousIndex else {
            return nil
        }

        return orderedViewControllers[previousIndex]
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.index(of: viewController) else {
            return nil
        }

        print(orderedViewControllers.index(of: viewController)) // Returns 0 is I swipe too fast, otherwise 1
        if let vc = orderedViewControllers[viewControllerIndex] as? WelcomeViewController {
            vc.delegate = self
        }

        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 nil
            // Uncommment the line below, remove the line above if you don't want the page control to loop.
            // return nil
        }

        guard orderedViewControllersCount > nextIndex else {
            return nil
        }

        return orderedViewControllers[nextIndex]
    }

}

我遇到过exactly一样的问题。它本质上可以归结为UIPageViewController (_UIQueuingScrollView准确地说)没有正确更新其视图层次结构。

我注意到UIPageViewController如果页面保持不变,它足够聪明,不会添加/删除内容视图(即使它位于视图层次结构中的错误位置,它也会以某种方式设法处理它,因此对用户来说看起来不错)。这就是为什么我添加了一个PageTrackingView观察内容视图被添加(或不添加)UIPageViewController查看层次结构。通过跟踪变化是否发生,我可以通过翻转它来计算当前索引。所以目前的解决方法足以满足仅 2 页.

class PageTrackingView: UIView {

    var pageIndexable: PageIndexable?

    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        if var pageIndexable = pageIndexable {
            let newIndex = (pageIndexable.internalIndex == 0) ? 1 : 0
            pageIndexable.internalIndex = newIndex
        }
        //Reset pageIndexable so that the index flip is fired only once
        pageIndexable = nil
    }
}

protocol PageIndexable {
    var internalIndex: Int { get set }
}

class PageViewController: UIPageViewController,
    UIPageViewControllerDataSource,
    UIPageViewControllerDelegate,
    PageIndexable {

    private var supportedViewControllers = [UIViewController]()

    internal var internalIndex: Int = 0 {
    didSet {
        if supportedViewControllers.indices.contains(internalIndex) {
            //Do something with the actual internalIndex value
        } else {
            assertionFailure()
        }
    }

    init(transitionStyle style: UIPageViewControllerTransitionStyle = .scroll,
        navigationOrientation: UIPageViewControllerNavigationOrientation = .horizontal,
        options: [String: Any]? = nil,
        viewControllers: [T]) {
        supportedViewControllers = viewControllers

        if !supportedViewControllers.isEmpty {
            let viewController = supportedViewControllers[0]
            let trackingView = PageTrackingView(frame: viewController.view.frame)
            viewController.view.frame = viewController.view.bounds
            trackingView.addSubview(viewController.view)
            viewController.view = trackingView
        }
        super.init(transitionStyle: style,
            navigationOrientation: navigationOrientation,
            options: options)
    }

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

        if !supportedViewControllers.isEmpty, let trackingView = supportedViewControllers[0].view as? PageTrackingView {
            trackingView.pageIndexable = self
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
        datasource = self
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

快速滚动 UIPageViewController 阻止视图控制器更新 的相关文章

随机推荐

  • 如何修复/调整 ggplot geom_tile 中每个带的宽度

    这是我的问题的示例数据 sampledata lt matrix c 1 60 1 60 rep 0 1 each 60 sample 1 3 120 replace T ncol 3 colnames sampledata lt c Ti
  • 如何进行递归子文件夹搜索并返回列表中的文件?

    我正在编写一个脚本 以递归方式遍历主文件夹中的子文件夹并构建特定文件类型的列表 我的脚本有问题 目前设置如下 for root subFolder files in os walk PATH for item in files if ite
  • Jquery AJAX:服务器端验证失败时如何显示Flash错误消息?

    我正在使用 Jquery 表单插件通过 ajax 提交表单 我已经在我的模型中的服务器端设置了验证 现在 当验证失败时 我想使用 ajax 向用户显示相同的 flash error 消息 如果验证成功 我可以显示 flash notice
  • Xcode 卡在索引上

    我已经工作了两个月的项目无缘无故停止工作 因为 Xcode 卡在 索引 上 我无法再构建该项目了 如果我尝试构建 Xcode 就会冻结 我必须强制退出 这种情况仅发生在该项目中 我尝试清理所有派生数据 但没有帮助 我正在使用 Xcode 4
  • jqgrid 更改单元格值并保持编辑模式

    我在网格中使用内联编辑 在某些情况下我想更改列内单元格的值 我用 setCell 更改它 效果很好 我的问题是 更改后 单元格失去了编辑模式 而该行的所有其他单元格都处于编辑模式 我想在更改单元格后将其保持在编辑模式 现在我所做的是保存该行
  • 种子中的 DHT

    我正在编写一个 P2P 实现 我希望将其去中心化 然而我在掌握如何做时遇到了一些困难DHT https en wikipedia org wiki Distributed hash table在像 BitTorrent 这样的协议中是有效的
  • 帮助正确计算atan2

    我需要计算线之间的角度 我需要计算atan 所以我正在使用这样的代码 static inline CGFloat angleBetweenLinesInRadians2 CGPoint line1Start CGPoint line1End
  • python中“追加”和“+”有什么区别? [复制]

    这个问题在这里已经有答案了 我不知道有什么区别f and g 功能中f 每当调用函数时 列表 L 就会累积 但在功能上g 它不是 def f a L L append 2 print L def g a L L L 2 print L pr
  • SQL Server 2008中的递归同表查询

    我在 SQL Server 2008 数据库中有下表 Id Name ParentFolder 1 Europe NULL 2 Asia NULL 3 Germany 1 4 UK 1 5 China 2 6 India 2 7 Scotl
  • echo 函数跳转到 Div 之外

    我创建了一个用于 gettext 翻译的函数 该函数位于头文件中 function ex text echo gettext text 当我使用函数 ex 时它会翻译该函数中的任何文本 效果很好 尽管当我在另一个内部有 div 的函数中使用
  • 使用 Apache Lucene 对 MySQL 数据库建立索引,并保持它们同步

    当MySQL中添加一个新项目时 它也必须被Lucene索引 当现有项目从 MySQL 中删除时 它也必须从 Lucene 的索引中删除 这个想法是编写一个脚本 通过调度程序 例如 CRON 任务 每 x 分钟调用一次 这是保持 MySQL
  • 简单的 Perl websocket 客户端

    我正在尝试用 Perl 编写一个简单的 websocket 客户端 use Protocol WebSocket Client my client Protocol WebSocket gt new url gt ws myserver p
  • 使用多核的 Numpy np.einsum 数组乘法

    我用MKL编译了numpy 1 6 2和scipy 希望有更好的性能 目前我有一个严重依赖 np einsum 的代码 并且我被告知 einsum 不适用于 MKL 因为几乎没有矢量化 所以我想用 np dot 和切片重新编写一些代码 只是
  • 预训练 Transformer 模型的配置更改

    我正在尝试为重整变压器实现一个分类头 分类头工作正常 但是当我尝试更改配置参数之一 config axis pos shape 即模型的序列长度参数时 它会抛出错误 Reformer embeddings position embeddin
  • IL 使用 Reflection.Emit 调用带有 params object[] 参数的方法

    我正在编写一个需要稍后类型构建的库 库使用平台 Net core 2 0 我使用 Reflection Emit 生成的某些类型存在问题 public class GeneratedA A IA public void DoInterfac
  • 为什么 git rebase 在我未修改的文件中显示冲突?

    假设我在本地仓库 其分支是my name branch A 当我做git rebase
  • XML::LibXML 文本节点父节点的概念

    这里似乎有些奇怪 在下面的示例中 我通过 XPath 查询访问文本节点 book isbn text The text 需要强制XML LibXML允许我使用XML LibXML Text方法 不过 要到达父节点 我必须调用parentNo
  • NSLocationWhenInUseUsageDescription 的 Xamarin.iOS 本地化

    有没有办法本地化NSLocationWhenInUseUsageDescription in Info plist在 Xamarin 工作室中 或者是否有可能将完整的内容本地化Info plist也将是一个解决方案 我尝试了以下步骤 因为它
  • 如何在 for 循环中制作按钮,并为每个按钮添加 lambda 表达式? [复制]

    这个问题在这里已经有答案了 我正在尝试用 javafx 制作一个刽子手游戏 因此 很自然地 我尝试使用 for 循环来创建每个按钮 而不是创建 26 个单独的按钮 我将它们放入名为 Alphabet 的 ArrayList 中 并将它们添加
  • 快速滚动 UIPageViewController 阻止视图控制器更新

    我有一个 UIPageviewcontroller 里面有两个控制器 当您滑动到下一个时 我使用 viewController 参数来设置适当的委托 但我的经验是 如果你滑动得太快 函数 viewControllerAfter 就无法正确更