Reputation: 31171
How do I make an instance of UIPageControl
appear immediately? (I have set defersCurrentPageDisplay
to NO
.)
I have an instance of UIPageControl
which is configured (number of pages, current page and then updated) when my view appears. However there is a short, fixed delay before it appears to the user. I'd like it to appear right away.
Otherwise it's working fine.
Upvotes: 0
Views: 786
Reputation: 538
I have fixed the delay issue by adding the UIPageViewController delegate's willTransitionToViewControllers and setting the pageController's index there:
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
for (MyContentPageViewController *contentController in pendingViewControllers) {
if ([contentController isKindOfClass:[MyContentPageViewController class]]) {
NSUInteger newIndex = contentController.pageIndex;
[self.pageControl setCurrentPage:newIndex];
}
}
Then, to avoid bugs in cases where swipe is not completed, add the following delegate method:
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
if(finished){
for (MyContentPageViewController *contentController in previousViewControllers) {
if ([contentController isKindOfClass:[MyContentPageViewController class]]) {
NSUInteger currentIndex = MIN(MAX(0, contentController.pageIndex), _allPages.count- 1);
[self.pageControl setCurrentPage:currentIndex];
}
}
} else {
for (MyContentPageViewController *contentController in previousViewControllers) {
if ([contentController isKindOfClass:[MyContentPageViewController class]]) {
NSUInteger currentIndex = MIN(MAX(0, contentController.pageIndex), _allPages.count);
[self.pageControl setCurrentPage:currentIndex];
}
}
}
}
Upvotes: 1
Reputation: 31171
The problem is I'm performing a lengthy background process and I've inadvertently and ultimately called updateCurrentPageDisplay
etc. from this secondary thread. UIKit
is not thread-safe and blocks this call until it can move it to the main thread, hence the delay.
To solve this, I've subclassed UIPageControl
creating "wrapper" methods that push calls to super
onto the main thread. I can then safely forget about this every time I need to speak with my page controls.
For example:
- (void) updateCurrentPageDisplay
{
@synchronized(self)
{
if ([UIDevice currentDeviceSupportsGrandCentralDispatch] == YES)
{
dispatch_async(dispatch_get_main_queue(), ^{
[super updateCurrentPageDisplay];
});
}
else
{
[super performSelectorOnMainThread:@selector(updateCurrentPageDisplay)
withObject:nil
waitUntilDone:NO];
}
}
}
Upvotes: 2