I'm loading views into a UIPageViewController and scrolling through them horizontally.
My issue is that when a view enters screen, it has a bigger size, and when the scroll finishes, it snaps to the size it should have.
Been trying to figure this out for a couple of hours now.
Anyone has had the same problem? how did you solve it?
I've checked these 2 links:
UIPageViewController changes size?
UIPageViewController has strange size
That made sense, but on my case, by doing that, I made the views too big on smaller devices, feels like the constraints aren't working, so I'm getting the bigger size here
I am not sure but try this:
// Disalbe translatesAutoresizingMaskIntoConstraints
self.pageViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
// Set up page view controller view constraints by using PureLayout
[self.pageViewController.view autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero]
please confine is it help ful or not ..
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
ImageViewController *contentVc = (ImageViewController *)viewController;
NSUInteger currentIndex = [_modelArray indexOfObject:[contentVc model]];
_vcIndex = currentIndex;
[_rateStepper setValue:[[contentVc model] rating]];
ImageModel *model = [_modelArray objectAtIndex:_vcIndex];
[_imageLabel setText:[NSString stringWithFormat:#"%# - Rating: %d", model.imageName, model.rating]];
if (currentIndex == 0)
{
return nil;
}
ImageViewController *imageViewController = [[ImageViewController alloc] init];
imageViewController.model = [_modelArray objectAtIndex:currentIndex - 1];
return imageViewController;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
ImageViewController *contentVc = (ImageViewController *)viewController;
NSUInteger currentIndex = [_modelArray indexOfObject:[contentVc model]];
_vcIndex = currentIndex;
[_rateStepper setValue:[[contentVc model] rating]];
ImageModel *model = [_modelArray objectAtIndex:_vcIndex];
[_imageLabel setText:[NSString stringWithFormat:#"%# - Rating: %d", model.imageName, model.rating]];
if (currentIndex == _modelArray.count - 1)
{
return nil;
}
ImageViewController *imageViewController = [[ImageViewController alloc] init];
imageViewController.model = [_modelArray objectAtIndex:currentIndex + 1];
return imageViewController;
}
If you build and run now, the pages will scroll, however we are still missing the page indicator view. We only need to implement the following dataSource methods as below:
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return _modelArray.count;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
Related
How does one ensure that the viewWillAppear: and viewDidAppear: (and other view transition methods) are called on a UIPageViewController's child ViewControllers?
In my case, the view transition methods are adequately called on all except for the very firstViewController that the UIPageViewController opens to. On that firstViewController, the viewDidAppear: and viewWillAppear: methods are actually called BEFORE the UIPageViewController's view transition methods. And then as one starts scrolling, the viewWillAppear: and viewDidAppear: methods are called as one would expect for the new view controllers.
Here is my structure: I have a BossViewController that contains an OrganizerViewController (a couple different organizers, actually, but that is irrelevant). The OrganizerViewController contains a UIPageViewController, which contains a series of CustomViewControllers. My code adequately calls the child view transition methods as per apple (https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html) for the interactions between the BossViewController and the OrganizerViewController (fully functional, perfectly so). The problem lies somewhere between the OrganizerViewController, it's child UIPageViewController, and it's first child CustomPageViewController.
I have tried calling beginAppearanceTransition: and endAppearanceTransition: within the UIPageViewController's viewWillAppear: and viewDidAppear: - but that resulted in an 'unbalanced calls' error log to console.
Here is the UIPageViewController set up code, all of which is in the OrganizerViewController:
- (void)configurePVC
{
NSDictionary *key = #{UIPageViewControllerOptionInterPageSpacingKey : #([UIScreen mainScreen].bounds.size.width * 0.5)};
_pvc = [[AVSCustomPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:key];
self.pvc.delegate = self;
self.pvc.dataSource = self;
_pvcArray = [[NSMutableArray alloc] init];
CustomViewController *daily = (CustomViewController *)[self viewControllerAtIndex:6];
self.index = 6;
[self.pvcArray addObject:daily];
[self.pvc setViewControllers:self.pvcArray
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
[self addChildViewController:self.pvc];
[self.dailyContainerView addSubview:self.pvc.view];
self.pvc.view.frame = self.dailyContainerView.bounds;
[self.pvc didMoveToParentViewController:self];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = [(CustomViewController *)viewController index];
if (index == 0) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [(CustomViewController *)viewController index];
if (index == 6) {
return nil;
}
index++;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
CustomViewController *viewController = [[CustomViewController alloc] init];
viewController.index = index;
return viewController;
}
I have a UIPageViewController that I've set up with an array as the datasource. I see the first page fine and the presentation count dots show up correctly, but when I try to drag the to the next page nothing happens. So I set up some breakpoints in the viewControllerAfterViewController as well as Before methods and they never get called on. The other dataSource methods for presentationCountForPageViewController get called on fine.
Any idea what I am missing? I've been going line by line with examples I've found on the web but can't find anything.
- (void)viewDidLoad
{
[super viewDidLoad];
UIPageViewController *pageController = self.pageController;
pageController.dataSource = self;
UIChildViewController *initialViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[initialViewController];
[pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
[self addChildViewController:pageController];
[self.view addSubview:pageController.view];
[pageController didMoveToParentViewController:self];
}
- (UIPageViewController *)pageController
{
return !_pageController ? _pageController =
({
UIPageViewController *value = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:nil];
value.view.frame = self.view.bounds;
value;
}) : _pageController;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pa geViewController viewControllerBeforeViewController:(UIChildViewController *)viewController
{
NSUInteger index = viewController.index;
return (index == 0 ) ? nil : [self viewControllerAtIndex:--index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIChildViewController *)viewController
{
NSUInteger index = viewController.index;
index++;
return (index == self.myDataSourceArray.count) ? nil : [self viewControllerAtIndex:index];
}
- (UIChildViewController *)viewControllerAtIndex:(NSUInteger)index
{
UIChildViewController *childViewController = [UIChildViewController new];
childViewController.view.frame = self.pageController.view.bounds;
childViewController.index = index;
...
return childViewController;
}
- (NSInteger)presentationCountForPageViewController: (UIPageViewController *)pageViewController
{
// The number of items reflected in the page indicator.
return self.myDataSourceArray.count;
}
- (NSInteger)presentationIndexForPageViewController:(UI PageViewController *)pageViewController
{
// The selected item reflected in the page indicator.
return 0;
}
The problem was that in including my UIViewController subclass which encapsulated the UIPageViewController, I forgot in the parent view controller's viewDidLoad to include addChildViewController and didMoveToParentViewController
[self addChildViewController:myViewController];
[self.view addSubview:myViewController.view];
[myViewControllerController didMoveToParentViewController:self];
Fixed the problem.
I am loading multiple UIViewControllers in UIPageViewController with each UIViewController having their own navigation bar. I have implemented all the required data source and delegate methods for UIPageViewController and it showing up correctly.
But when I scroll my view controller horizontally, more often, I see a white blank screen instead of my view controller. Below is my code.
Any clue what could be wrong here.
PS: I tried by removing the IF condition in my viewControllerForRequestID method and returning a new controller every time. This works but then I end up with one view controller showing up twice in pagination.
- (UIViewController *)pageViewController:(UIPageViewController *)iPageViewController viewControllerBeforeViewController:(UIViewController *)iViewController {
[self.pageControl setCurrentPage:self.selectedRequestIndex];
if (self.selectedRequestIndex == 0) {
return nil;
}
NSUInteger aNewSelectedRequestIndex = self.selectedRequestIndex - 1;
NSString *aPreviousRequestID = [self.paginationRequestIDList[aNewSelectedRequestIndex] stringValue];
self.selectedRequestIndex = aNewSelectedRequestIndex;
self.selectedRequestID = aPreviousRequestID;
return [self viewControllerForRequestID:self.selectedRequestID];
}
- (UIViewController *)pageViewController:(UIPageViewController *)iPageViewController viewControllerAfterViewController:(UIViewController *)iViewController {
[self.pageControl setCurrentPage:self.selectedRequestIndex];
if (self.selectedRequestIndex == NSNotFound || self.selectedRequestIndex >= self.paginationRequestIDList.count - 1) {
return nil;
}
NSUInteger aNewSelectedRequestIndex = self.selectedRequestIndex + 1;
NSString *aNextRequestID = self.paginationRequestIDList[aNewSelectedRequestIndex];
self.selectedRequestIndex = aNewSelectedRequestIndex;
self.selectedRequestID = aNextRequestID;
return [self viewControllerForRequestID:self.selectedRequestID];
}
- (MyNavigationViewController *)viewControllerForRequestID:(id)iRequestID {
NSString *aRequestID = iRequestID;
// Safe check to avoid numbers in request ID
if (![iRequestID isKindOfClass:[NSString class]]) {
aRequestID = [iRequestID stringValue];
}
#synchronized (self) {
if ([self.viewControllers containsObjectForKey:iRequestID]) {
MyNavigationViewController *aNavigationController = self.viewControllers[iRequestID];
return aNavigationController;
}
MyDataModel *aRequestData = self.savedRequestData[iRequestID];
MyDataModelController *aRequestInfoController = [[MyDataModelController alloc] initWithRequestData:aRequestData];
aRequestInfoController.delegate = self;
MyNavigationViewController *aNavigationController = [[MyNavigationViewController alloc] initWithRootViewController:aRequestInfoController];
[self.viewControllers setObject:aNavigationController forKey:iRequestID];
return aNavigationController;
}
}
I bought this project (http://codecanyon.net/item/turnthepdf/2417301/support) to use in my application but it is not detecting links inside PDF file. For example, page index works in webview but not working in this library.
I tried to search in internet about configuring UIPageViewController but no result.
#pragma mark Debug / Utility
- (int) currentPage
{
int pageCheck = ((UIViewController *)[self.viewControllers objectAtIndex:0]).view.tag;
return pageCheck;
}
#pragma mark Page Handling
// Update if you'd rather use some other decision style
- (BOOL) useSideBySide: (UIInterfaceOrientation) orientation
{
BOOL isLandscape = UIInterfaceOrientationIsLandscape(orientation);
return isLandscape;
}
// Store the new page and update the delgate
- (void) updatePageTo: (uint) newPageNumber
{
pageNumber = newPageNumber;
[[NSUserDefaults standardUserDefaults] setInteger:pageNumber forKey:DEFAULTS_BOOKPAGE];
[[NSUserDefaults standardUserDefaults] synchronize];
SAFE_PERFORM_WITH_ARG(bookDelegate, #selector(bookControllerDidTurnToPage:), [NSNumber numberWithInt:pageNumber]);
}
// Request controller from delegate
- (UIViewController *) controllerAtPage: (int) aPageNumber
{
if (bookDelegate &&
[bookDelegate respondsToSelector:#selector(viewControllerForPage:)])
{
UIViewController *controller = [bookDelegate viewControllerForPage:aPageNumber];
controller.view.tag = aPageNumber;
return controller;
}
return nil;
}
// Update interface to the given page
- (void) fetchControllersForPage: (uint) requestedPage orientation: (UIInterfaceOrientation) orientation
{
BOOL sideBySide = [self useSideBySide:orientation];
int numberOfPagesNeeded = sideBySide ? 2 : 1;
int currentCount = self.viewControllers.count;
uint leftPage = requestedPage;
if (sideBySide && (leftPage % 2)) leftPage--;
// Only check against current page when count is appropriate
if (currentCount && (currentCount == numberOfPagesNeeded))
{
if (pageNumber == requestedPage) return;
if (pageNumber == leftPage) return;
}
// Decide the prevailing direction by checking the new page against the old
UIPageViewControllerNavigationDirection direction = (requestedPage > pageNumber) ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse;
[self updatePageTo:requestedPage];
// Update the controllers
NSMutableArray *pageControllers = [NSMutableArray array];
SAFE_ADD(pageControllers, [self controllerAtPage:leftPage]);
if (sideBySide)
SAFE_ADD(pageControllers, [self controllerAtPage:leftPage + 1]);
[self setViewControllers:pageControllers direction: direction animated:YES completion:nil];
}
- (void)viewDidLoad {
}
// Entry point for external move request
- (void) moveToPage: (uint) requestedPage
{
[self fetchControllersForPage:requestedPage orientation:(UIInterfaceOrientation)[UIDevice currentDevice].orientation];
}
#pragma mark Data Source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
[self updatePageTo:pageNumber - 1];
return [self controllerAtPage:(viewController.view.tag - 1)];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
[self updatePageTo:pageNumber + 1];
return [self controllerAtPage:(viewController.view.tag + 1)];
}
/*
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
[self updatePageTo:pageNumber + 1];
return [self controllerAtPage:(viewController.view.tag + 1)];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
[self updatePageTo:pageNumber - 1];
return [self controllerAtPage:(viewController.view.tag - 1)];
}
*/
#pragma mark Delegate
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
NSUInteger indexOfCurrentViewController = 0;
if (self.viewControllers.count)
indexOfCurrentViewController = ((UIViewController *)[self.viewControllers objectAtIndex:0]).view.tag;
[self fetchControllersForPage:indexOfCurrentViewController orientation:orientation];
BOOL sideBySide = [self useSideBySide:orientation];
self.doubleSided = sideBySide;
UIPageViewControllerSpineLocation spineLocation = sideBySide ? UIPageViewControllerSpineLocationMid : UIPageViewControllerSpineLocationMin;
return spineLocation;
}
#pragma mark Class utility routines
// Return a UIViewController that knows how to rotate
+ (id) rotatableViewController
{
UIViewController *vc = [[RotatableVC alloc] init];
return vc;
}
// Return a new book
+ (id) bookWithDelegate: (id) theDelegate
{
BookController *bc = [[BookController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
bc.dataSource = bc;
bc.delegate = bc;
bc.bookDelegate = theDelegate;
return bc;
}
Annotations inside a pdf is not able to render in iOS devices to render forms or annotations you can go for a good library.
Pdf Tron Library
You can also see the below link it might help.
Get pdf hyperlinks on ios
I've been trying to use the UIPageViewController to display 3 different nibs for a few days on and off now and have almost got it working. I still have one weird bug that I cant figure out.
Basically the app starts, I can scroll between the 3 pages one after another with out any problems, eg:
Page1->Page2->Page3
and then back to the start:
Page3->Page2->Page1.
No Problems. The issue is that if I scroll, for example from Page3->Page2, then BACK to Page3, Page3 Dissappears when it snaps into place. If I scroll to where a forth page would be, then I get Page3. Here is the code relevant to the UIPageViewController, the nibs and the delegate methods for the UIPageViewController:
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.delegate = self;
[[self.pageViewController view] setFrame:[[self view] bounds]];
indexTest = 0;
Page1 *p1 = [[Page1 alloc]initWithNibName:#"Page1" bundle:nil];
p1.view.tag = 1;
Page2 *p2 = [[Page2 alloc]initWithNibName:#"Page2" bundle:nil];
p2.view.tag = 2;
Page3 *p3 = [[Page3 alloc]initWithNibName:#"Page3" bundle:nil];
p3.view.tag = 3;
NSArray *arr = [[NSArray alloc] initWithObjects:p1,nil];
viewControllers = [[NSMutableArray alloc] initWithObjects:p1,p2,p3, nil];
[self.pageViewController setViewControllers:arr direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
self.pageViewController.dataSource = self;
[self addChildViewController:self.pageViewController];
[[self view] addSubview:[self.pageViewController view]];
[self.pageViewController didMoveToParentViewController:self];
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
}
#pragma mark - page view controller stuff
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
if (indexTest > 0) {
switch (indexTest) {
case 1:{
NSLog(#"NO page is BEFORE current page");
break;
}
case 2:{
NSLog(#"Page BEFORE is Page: %#", [NSString stringWithFormat:#"%#",[viewControllers objectAtIndex:0] ] );
indexTest--;
return [viewControllers objectAtIndex:0];
break;
}
default:{
NSLog(#"PROBLEM in viewBEFORE, indexTest = %d!!!!", indexTest);
break;
}
}
}
return nil;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
if (indexTest < NUM_OF_PAGES) {
switch (indexTest) {
case 0:{
NSLog(#"Page AFTER is Page: %#", [NSString stringWithFormat:#"%#",[viewControllers objectAtIndex:1] ] );
indexTest++;
return [viewControllers objectAtIndex:1];
break;
}
case 1:{
NSLog(#"Page AFTER is Page: %#", [NSString stringWithFormat:#"%#",[viewControllers objectAtIndex:2] ] );
indexTest++;
return [viewControllers objectAtIndex:2];
break;
}
case 2:{
NSLog(#"No pages AFTER this current page %d", indexTest);
break;
}
default:{
NSLog(#"PROBLEM in viewAFTER, indexTest = %d!!!!", indexTest);
break;
}
}
}
return nil;
}
Finally the page index dots code
#pragma mark - dot controller
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
// The number of items reflected in the page indicator.
return NUM_OF_PAGES;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
// The selected item reflected in the page indicator.
return 0;
}
Any and all help is much appreciated, I think I'm just doing something silly that I cant see as I'm so close to it fully working. If anythings not clear or I haven't give enough information please let me know and I'll answer it as best as I can.
Thanks
I think your indexTest logic is wrong, it's showing the wrong indexes for the viewControllers. I wouldn't use those methods to keep track of the index as they can be called even when the views aren't actually going to change.
Instead you could replace the selection of view controllers like this:
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
int vcIndex = [self.viewControllers indexOfObject:viewController];
if (vcIndex > 0) {
return [self.viewControllers objectAtIndex:vcIndex-1];
}
return nil;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
int vcIndex = [self.viewControllers indexOfObject:viewController];
if (vcIndex < NUM_OF_PAGES-1) {
return [self.viewControllers objectAtIndex:vcIndex+1];
}
return nil;
}
And if you need to keep track of the current index, use the delegate method provided.
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
if (completed && finished) {
UIViewController *currentVC = pageViewController.viewControllers[0];
indexTest = [self.viewControllers indexOfObject:currentVC];
}
}
Just note that if your using this method, don't call setViewControllers: amimated:YES as this will lose track of the correct position.
Side note: I too have been struggling with UIPageViewController and found it was quicker and easier to write my own version. I think it has too many bugs.