Refresh UIPageViewController - reorder pages and add new pages
Solution 1
You need to call setViewControllers:direction:animated:completion:
.
Also, in iOS 6, watch out if you're using UIPageViewControllerTransitionStyleScroll style, as there is a major caching bug if animated:
is YES (see my discussion here: UIPageViewController navigates to wrong page with Scroll transition style).
Solution 2
I found a workaround to force UIPageViewController
to forget about cached view controllers of neighboring pages that are currently not displayed:
pageViewController.dataSource = nil;
pageViewController.dataSource = self;
I do this everytime I change the set of pages. Of course this doesn't affect the currently displayed page.
With this workaround I avoid the caching bug and can still use animated:YES
in setViewControllers:direction:animated:completion:
.
Solution 3
Here's my complete implementation of @ortwin-gentz's answer in the didFinish delegate method in Swift 2, which works perfectly for me:
func pageViewController(
pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool
) {
if !completed { return }
dispatch_async(dispatch_get_main_queue()) {
pageViewController.dataSource = nil
pageViewController.dataSource = self
}
}
Solution 4
Swift 4 Version for reload of data of pageviewcontroller, to @theory's version.
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if !completed { return }
DispatchQueue.main.async() {
self.dataSource = nil
self.dataSource = self
}
}
ssloan
Updated on July 09, 2022Comments
-
ssloan almost 2 years
I have a
UIPageViewController
which I am providing page data for using an implementation ofUIPageControllerDelegate
andUIPageControllerDataSource
.It's all working fine, but I want to be able to add items to the page data and reorder the page data.
If a user has already got to the last of the pages, and then I add an item, they can't get to the next page because
viewControllerAfterViewController:
has already been called. If they scroll back one and then forward two they can get to the new page fine, so the data is setup correctly. How can I tell theUIPageViewController
to refresh its store of what comes next?Similarly I would like to reorder the collection that is backing the page view. But if I do this I'll get the same problem - the page view will think the next page is still what it was last time the current page was loaded.
I guess I'm looking for something similar to
reloadData:
onUITableView
. -
ssloan about 11 yearsThanks - the setViewControllers:direction:animated:completion: did it. Cheers for mentioning the bug too.
-
ernesto about 10 yearsInteresting. Where do you unset and reset the dataSource? Before
setViewControllers:direction:animated:completion:
, after it, or in the completion block? Thanks. -
Ortwin Gentz about 10 yearsActually, I do this 0.01 seconds after didFinish in a dispatch_async block.
-
Michael McGuire over 9 yearsThank you! This method works when using a data source. The accepted answer didn't work for me, at least on iOS 8. Using "setViewControllers:direction:animated:completion:" with the current view controller did not cause the data source to be called again.
-
Alex Sfinx87 almost 9 yearsThx for this solution. :-)
-
Mr.Fingers about 8 yearstip: After you reset
dataSource
(a.k.a.pageViewController.dataSource = nil;
) your method-viewControllerBefore
and-viewControllerAfter
will be called again. For restore the dataSource. -
Ozgur Vatansever about 8 yearsYou need to reassign dataSource like above if
presentationCountForPageViewController
returns a dynamic value which might change after the refresh. -
BaseZen over 7 yearsDouble plus good. Why this is not documented -- inexcusable. Confirmed for iOS 10, Swift 2.3, Xcode 8
-
Kartick Vaddadi about 7 yearsThis doesn't work, at least not in iOS 10.3. The crash happens in setViewControllers(), so doing something 0.01 seconds afterward is too late. I tried this trick before calling setViewControllers(), and it doesn't work.
-
Gon almost 7 yearsdoesn't work iOS 10 when you call
setViewControllers:direction:animated:completion:
fast enough, still got wrong content offset. -
Uday Kumar Eega about 6 yearsWorked like charm...Perfect..Thanks
-
DJTano over 3 yearsAnd what if I also want to update the currently displayed page ?
-
Ortwin Gentz over 3 years@DJTano that's the purpose of
setViewControllers:direction:animated:completion:
. Even though it asks for an array of view controllers, you usually send a single array (exception is a 2-element array ifspineLocation = .mid
) with the current VC. -
DJTano over 3 years@OrtwinGentz got it. Thanks!! :)