Call both of After and Before Method in UIPageView

2019-06-14 17:22发布

I made UIPageViewController with datasource array and it's works correctly. But when swiping to right for forwarding call both of After and Before methods.
My codes is here:

import UIKit

class MainPageViewController: UIPageViewController,UIPageViewControllerDataSource {


override func viewDidLoad() {
    super.viewDidLoad()

    self.dataSource = self
initUPageVC(idx:0,isAnimate:false,direction: UIPageViewControllerNavigationDirection.forward)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
{

    //PRIVIOUS
    let pageContent: MainPageContentViewController = viewController as! MainPageContentViewController

    var index = pageContent.index

    if ((index == 0) || (index == NSNotFound))
    {
        return nil
    }

    index -= 1;

    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateMenuBarItemSelectedNotif"), object: index)

    return getViewControllerAtIndex(index)
}

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

    //NEXT
    let pageContent: MainPageContentViewController = viewController as! MainPageContentViewController

    print("now n",pageContent.index)

    var index = pageContent.index

    if (index == NSNotFound)
    {
        return nil;
    }

    index += 1;

    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateMenuBarItemSelectedNotif"), object: index)

    return getViewControllerAtIndex(index)
}
func getViewControllerAtIndex(_ index: Int) -> MainPageContentViewController
{
    // Create a new view controller and pass suitable data.

    let destinationVC = self.storyboard?.instantiateViewController(withIdentifier: "MainPageContentVCID") as! MainPageContentViewController

    destinationVC.index = index


    return destinationVC
}
func initUPageVC(idx:Int,isAnimate:Bool,direction:UIPageViewControllerNavigationDirection) {

    self.setViewControllers(
        [getViewControllerAtIndex(idx)],
        direction: direction,
        animated: isAnimate, completion: nil)

    let destinationVC = self.storyboard?.instantiateViewController(withIdentifier: "MainPageContentVCID") as! MainPageContentViewController

    destinationVC.index = idx

}  

And child vc code here:

import UIKit

class MainPageContentViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {

@IBOutlet var tableView: UITableView!
var dataSource : Array<Item>!
var index:Int = 0
var myStr:String!

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.register(UINib(nibName: "ItemCellNib", bundle: nil), forCellReuseIdentifier: "ItemCellIdentifier")

    prepareData()

}
//MARK: Table View
func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataSource.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCellIdentifier", for: indexPath) as! ItemTableViewCell

    let obj = dataSource[indexPath.row]

    cell.itemImage.image = UIImage(named:obj.imageName)




    cell.selectionStyle = UITableViewCellSelectionStyle.none

    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let obj = dataSource[indexPath.row]
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "itemHasClickedNotif"), object: obj)
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 197
}

func prepareData(){
    let obj0 = Item()
    let obj1 = Item()
    let obj2 = Item()
    let obj3 = Item()

    if index == 0 {

    obj0.ID = 0
    obj0.imageName = "dog"

    obj1.ID = 1
    obj1.imageName = "dog"

    obj2.ID = 2
    obj2.imageName = "dog"

    obj3.ID = 3
    obj3.imageName = "dog"

}else if index==1{

obj0.ID = 0
obj0.imageName = "cat"

obj1.ID = 1
obj1.imageName = "cat"

obj2.ID = 2
obj2.imageName = "cat"

obj3.ID = 3
obj3.imageName = "cat"
}else{
obj0.ID = 0
obj0.imageName = "lion"

obj1.ID = 1
obj1.imageName = "lion"


obj2.ID = 2
obj2.imageName = "lion"


obj3.ID = 3
obj3.imageName = "lion"

}


    dataSource = [obj0,obj1,obj2,obj3]

    tableView.setContentOffset(CGPoint.zero, animated: false)

    tableView.reloadData()
}
}  

Please help me to fix this problem Thank you.

2条回答
走好不送
2楼-- · 2019-06-14 17:29

Here is how you can make it swipe and give you the correct index:

func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
guard let index = controllers.firstIndex(of: pendingViewControllers.first! as! PhotoViewController) else { return }
photoReviewerDelegate?.userDidSwipe(at: index)

}

查看更多
Viruses.
3楼-- · 2019-06-14 17:39

It isn't a problem with the page view controller. It's a problem with your assumptions about when viewControllerBefore and viewControllerAfter are called. Your assumptions seem reasonable, but they are wrong, as I will now explain.

You are assuming, for example, that when I am in, say, page 3 and I start to swipe to page 4, viewControllerAfter is called for page 3 so that you can submit page 4. That is not true. The scroll implementation of page view controller uses caching and lookahead to make scrolling faster. Thus, when you do what I just described, it may be that page 4 has already been cached, and now, when the scroll ends, the PVC will call viewControllerAfter for page 5, in order to pre-cache it in case you scroll again the same way later. Or, if this is the last page, it may be that nothing will be called at all.

This behavior means that you cannot make any assumptions about when viewControllerBefore and viewControllerAfter are called or for what page they are called. But your code, with your use of notifications in those methods, depends upon such assumptions — and those assumptions are wrong, and that is why your code isn't working. Everything seems to you to be off-by-one — because it is.

You might be able to solve the problem by relying for your signals instead on the delegate methods willTransitionTo and didFinishAnimating (see the docs on UIPageViewControllerDelegate).

查看更多
登录 后发表回答