uias / Pageboy

📖 A simple, highly informative page view controller
MIT License
1.99k stars 154 forks source link

Screen got blank when trying to swipe fast #144

Open aaasifrz9 opened 6 years ago

aaasifrz9 commented 6 years ago

Hi,

I have added 5-6 child controllers. Now when I am swiping from start to end controller. Sometimes child view controller got blank while content on parent controller is properly showing. Then now when swiping back/forward, it shows child controller contents and again blanks. Tried sometimes back/forward then it loads child controller. It is not giving me any log in console. So I am not able to understand what is happening here.

Please help. Thanks in advance.

msaps commented 6 years ago

@aaasifrz9 hi, do you have a video or something that shows this? I'm find it hard to reproduce. Your PageboyViewControllerDataSource set up may also be useful 👍

aaasifrz9 commented 6 years ago

Hi @msaps ,

I have printed PageboyViewControllerDataSource and PageboyViewControllerDelegate logs in below link. Please check. Link: https://www.dropbox.com/s/2qxyx4vli71fg0p/Archive.zip?dl=0

aaasifrz9 commented 6 years ago

Hi @msaps ,

Please take a look also. I have added 6 childs VC and when I tried to scroll it fast then the log is in the attached file. I don't understand didScrollToPosition jump to index 5 then 1 then 4 and again come back to 1 point something. Take a look lines from 6-11. And blank screen comes on line 8-10. Please help how to handle. It's too much critical for me. Thanks in advance.

Log.rtf.zip

aaasifrz9 commented 6 years ago

Hi @msaps ,

My PageBoyViewController code is like

var pageControllers: [ChildViewController]!

After that in viewDidLoad, I fetch data from server than created

let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)

var viewControllers = [ChildViewController]()
for i in 0 ..< numberOfPages {
    let viewController = storyboard.instantiateViewController(withIdentifier: "ChildViewController") as! ChildViewController
    viewController.index = i
    if i == 0 {
        self.currentChildViewController = viewController
    }
    viewController.delegate = self
    viewControllers.append(viewController)
}
self.pageControllers = viewControllers

Then I set

dataSource = self
delegate = self
extension PageViewController: PageboyViewControllerDataSource {

    func numberOfViewControllers(in pageboyViewController: PageboyViewController) -> Int {
        return self.pageControllers.count
    }

    func viewController(for pageboyViewController: PageboyViewController,
                        at index: PageboyViewController.PageIndex) -> UIViewController? {
        return self.pageControllers[index]
    }

    func defaultPage(for pageboyViewController: PageboyViewController) -> PageboyViewController.Page? {
        return nil
    }
}

// MARK: PageboyViewControllerDelegate
extension PageViewController: PageboyViewControllerDelegate {

    func pageboyViewController(_ pageboyViewController: PageboyViewController,
                               willScrollToPageAt index: Int,
                               direction: PageboyViewController.NavigationDirection,
                               animated: Bool) {
                        print("willScrollToPageAtIndex: \(index)")
    }

    func pageboyViewController(_ pageboyViewController: PageboyViewController,
                               didScrollTo position: CGPoint,
                               direction: PageboyViewController.NavigationDirection,
                               animated: Bool) {
                        print("didScrollToPosition: \(position)")
    }

    func pageboyViewController(_ pageboyViewController: PageboyViewController,
                               didScrollToPageAt index: Int,
                               direction: PageboyViewController.NavigationDirection,
                               animated: Bool) {
                        print("didScrollToPageAtIndex: \(index)")
    }

    func pageboyViewController(_ pageboyViewController: PageboyViewController,
                               didReloadWith currentViewController: UIViewController,
                               currentPageIndex: PageboyViewController.PageIndex) {
        print("didReloadWith)")
    }
}

I am not able to recognise why it jumps as described in above comment and show blank screen. Please help, thanks in advance.

msaps commented 6 years ago

@aaasifrz9 hmm your code all looks good. I'll investigate and see what I can find, maybe something strange in the page detection logic. Weird it hasn't come up before though!

aaasifrz9 commented 6 years ago

Hi @msaps ,

I analyzed that when we try to scroll fast then x position jumps from current page to last/next to next page directly.

Can we load next/previous page when current page loads as like UIPagerViewController using PageBoy framework? If possible, please suggest how can we implement?

Regards, Asif

DamonChen117 commented 6 years ago

I got a whole white view sometimes.

aaasifrz9 commented 6 years ago

Yes, white because parent view controller's background color is white. In my case I am getting whole black due to black background color.

msaps commented 6 years ago

@DamonChen117 @aaasifrz9 how hard is this to reproduce? It is probably a UIPageViewController issue, could be related to the discussion in #113?

Any concrete reproduction steps, demo projects or videos would be much appreciated.

aaasifrz9 commented 6 years ago

Hi @msaps ,

As per comment in #151 , the viewController(for: at:) data source function is called whenever the internal UIPageViewController asks for a view controller in pageViewController(viewControllerBefore:) or pageViewController(viewControllerAfter:) but when I swipe it only load current view controller. And UIPageViewController loads current and next/previous as per swipe direction also.

My question is:-

Can we load next/previous page also when current page loads as like UIPageViewController using PageBoy framework?

Actually I think if we can load next/previous view controller also then may be can it resolves jump problem here.

If possible, please suggest how can we implement?

Thanks for above response.

msaps commented 6 years ago

@aaasifrz9 what I was meaning by that comment is that the data source in PageboyViewController behaves exactly like UIPageViewController as that is what it is using underneath. So the 'next' view controller is loaded at the exact same time as it would be using a raw UIPageViewController.

gaborcsontos commented 6 years ago

Same. Sometimes its totally goes black.

aaasifrz9 commented 6 years ago

Hi @msaps ,

I can understand that Pageboy is using UIPageViewControllerDataSource internally but it is not loading next/prev view controller as UIPageViewController loading. Has jump/black screen issue solved? Please help.

msaps commented 6 years ago

@aaasifrz9 as you can see and I have specified, PageboyViewController will ask for the next/previous view controller in the exact same way as UIPageViewController. It is just masked by a different data source:

screen shot 2018-03-27 at 10 03 46

The issue itself I am still investigating.

msaps commented 6 years ago

@aaasifrz9 @DamonChen117 @gaborcsontos think this is related to #157 - and I also believe I might have found a fix 🎉

msaps commented 6 years ago

@aaasifrz9 @DamonChen117 @gaborcsontos can you check out 2.5.0 and see how you get on...

(If you're using Tabman, I'll release a new version tomorrow that uses Pageboy 2.5)

Vapor-ios commented 6 years ago

I am still having this issue... takes a while of scrolling really fast and like crazy, this never happened to me in normal conditions... got this in 2.6.1 and 3.0 too

Vapor-ios commented 6 years ago

I have this issue especially when swiping very fast (even using 3-4 fingers) and getting these error messages: <_UISystemGestureGateGestureRecognizer: 0x2800c40f0>: Gesture: Failed to receive system gesture state notification before next touch

I know this is a corner case but I thought you'd like to know and maybe fix it somewhere in the future.

RamblinWreck77 commented 5 years ago

@msaps I was able to cause this to happen.

Basic structure:

-Parent page controller, child pages. Child page custom delegate type = parent

-child pages communicate back to parent page controller via delegate pattern

-Button press on child view controller (page 1) calls out to delegate "go to 2nd page"

-Parent method looks like this:

/// Child delegate callback
func goToSecond() {
   setViewControllers([second],
                          direction: .forward,
                          animated: true,
                          completion: nil)
}

Here's the kicker: The button on the child controller called the "delegate?.goToSecond()" on touch down from a UIButton, so what could happen is the user could hypothetically tap twice VERY QUICKLY, call the delegate twice, thus calling the above function twice very rapidly, and boom you now have a black screen. It's possible this is the same issue with "swiping too fast". Idk if it's relevant but for this page controller there were also only two pages total. So 1st page, then extremely rapid duplicate calls to the above function (which is also the last page in the collection) can cause this.

dfmarulanda commented 5 years ago

I have this problem. Does it have a workaround? ezgif-1-5d9192d2b678

sugitatestblue commented 2 years ago

@dfmarulanda Do you call super class methods also?