UIPageController:快速向前然后向后翻页只更新第一页

UIPageController: Turning the page forward then backward quickly only updates the first page

我有 class SliderPgaeViewController: UIPageViewController 滚动过渡样式如下:

class SliderPgaeViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource, PlayerUpdatePageControllerDelegate {


var lastPendingIndex: Int = 0
var sliderPageDelegate: SliderPageDelegate? = nil
let playerManager = PlayerManager.getInstance()

override func viewDidLoad() {
    super.viewDidLoad()

    self.dataSource = self
    self.delegate = self
    setViewControllers([createViewController(index: playerManager.getCurrentIndex())!], direction: .forward, animated: true, completion: nil)
    lastPendingIndex = playerManager.getCurrentIndex()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

func presentationCount(for pageViewController: UIPageViewController) -> Int {
    return playerManager.getSongsCount()
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
    if let vc = viewController as? PlayerImageViewController {
        if (vc.index == 0){
            return nil
        }
        return createViewController(index: vc.index! - 1)
    }
    return nil

}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
    if let vc = viewController as? PlayerImageViewController {
        if (vc.index == playerManager.getSongsCount() - 1){
            return nil
        }
        return createViewController(index: vc.index! + 1)
    }
    return nil
}


func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]){
    if let vc = pendingViewControllers[0] as? PlayerImageViewController {
        self.lastPendingIndex = vc.index!
    }
}

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool,previousViewControllers: [UIViewController],transitionCompleted completed: Bool) {
    print("before completion : \(self.lastPendingIndex)")
    if(completed){
        print("completed : \(self.lastPendingIndex)")
        if (viewControllers?.first as? PlayerImageViewController) != nil {
            sliderPageDelegate?.updateSong(index: self.lastPendingIndex, dir: 0)
        }
    }
}

private func createViewController(index i: Int) -> UIViewController?{
    let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PlayerImageController") as! PlayerImageViewController
    vc.index = i
    vc.image = playerManager.getSong(index: i).image
    return vc
}
...

我正在使用此页面控制器在音乐播放器中显示歌曲的缩略图。当用户翻页时,播放器通过调用 pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool,previousViewControllers: [UIViewController],transitionCompleted completed: Bool)

中的 sliderPageDelegate?.updateSong(index: self.lastPendingIndex, dir: 0) 来更改正在播放的歌曲

当我向前翻页然后立即向后翻页时,翻页正确(先向前再向后);但是,sliderPageDelegate?.updateSong(index: self.lastPendingIndex, dir: 0) 仅在正向调用。

因此,如果我们有歌曲列表 (A, B, C, ...) 并且我们目前正在播放歌曲 A。当用户向前滑动时,缩略图变为 B's 缩略图,播放器将歌曲更新为 B。但是,如果向前滑动后快速向后滑动,则缩略图会变为 A,但歌曲仍为 B

更新:

如果 Aindex = 0 并且 Bindex = 1,快速移动 A->B->A 将打印以下内容:

before completion : 1
before completion : 1
completed : 1

我在您的代码中添加了 PageControllerDelegate 并引入了两个新方法。然后在 UIPageViewController class 中实现这些委托,然后在 PlayerImageViewController class 中调用 viewWillAppearviewWillDisappear 中的两个方法。现在删除您的 didFinishAnimation 方法并将该代码写入 viewControllerIsBeingDisplay.

如需更深入的了解,请查看此代码。

class PlayerImageViewController: UIViewController {
    var index: Int?
    var image: UIImage?
    weak var delegate: PageControllerDelegate?


    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if let del = self.delegate {
            del.viewControllerIsBeingHide(self)
        }
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if let del = self.delegate {
            del.viewControllerIsBeingDisplay(self)
        }
    }
}
protocol SliderPageDelegate {
    func updateSong(index: Int, dir: Int)
}
protocol PageControllerDelegate {
    func viewControllerIsBeingHide(_ viewController: PlayerImageViewController)
    func viewControllerIsBeingDisplay(_ viewController: PlayerImageViewController)
}
class SliderPgaeViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource, PageControllerDelegate {


    var lastPendingIndex: Int = 0
    var sliderPageDelegate: SliderPageDelegate? = nil

    override func viewDidLoad() {
        super.viewDidLoad()

        self.dataSource = self
        self.delegate = self
        setViewControllers([createViewController(index: playerManager.getCurrentIndex())!], direction: .forward, animated: true, completion: nil)
        lastPendingIndex = playerManager.getCurrentIndex()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func presentationCount(for pageViewController: UIPageViewController) -> Int {
        return playerManager.getSongsCount()
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        if let vc = viewController as? PlayerImageViewController {
            if (vc.index == 0){
                return nil
            }
            return createViewController(index: vc.index! - 1)
        }
        return nil

    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        if let vc = viewController as? PlayerImageViewController {
            if (vc.index == playerManager.getSongsCount() - 1){
                return nil
            }
            return createViewController(index: vc.index! + 1)
        }
        return nil
    }


    func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]){
        if let vc = pendingViewControllers[0] as? PlayerImageViewController {
            self.lastPendingIndex = vc.index!
        }
    }


    private func createViewController(index i: Int) -> UIViewController?{
        let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PlayerImageController") as! PlayerImageViewController
        vc.index = i
        vc.delegate = self
//        vc.image = playerManager.getSong(index: i).image //Commented becoz i do not have this file
        return vc
    }
    var previousVCIndex = 0

    func viewControllerIsBeingHide(_ viewController: PlayerImageViewController) {
        previousVCIndex = viewController.index!
    }
    func viewControllerIsBeingDisplay(_ viewController: PlayerImageViewController) {
        if let del = sliderPageDelegate {
            del.updateSong(index: previousVCIndex, dir: 0)
        }
    }
}