ios - tutorial - uipageviewcontroller swift 4
Cómo agregar dos controladores de vista en UIPageViewcontroller (4)
Estoy usando UIPageViewController
en iPad donde necesito mostrar un firstviewController
en la primera página y ContentViewController
en la página siguiente en horizontal.
Si configuro NSArray
con dos viewControllers
la aplicación se bloquea en [self.pagviewController setViewController:]
con la siguiente excepción:
El número de controladores de vista proporcionados (2) no coincide con el número requerido (1) para la ubicación de la columna vertebral solicitada (UIPageViewControllerSpineLocationMin)
A continuación se muestra el código:
#pragma mark - UIPageViewControllerDataSource Methods
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)viewController textContents]];
if(currentIndex == 0)
{
return nil;
}
ContentViewController *contentViewController = [[ContentViewController alloc] init];
contentViewController.textContents = [self.modelArray objectAtIndex:currentIndex - 1];
return contentViewController;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)viewController textContents]];
if(currentIndex == self.modelArray.count-1)
{
return nil;
}
ContentViewController *contentViewController = [[ContentViewController alloc] init];
contentViewController.textContents = [self.modelArray objectAtIndex:currentIndex + 1];
return contentViewController;
}
//#pragma mark - UIPageViewControllerDelegate Methods
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
if(UIInterfaceOrientationIsPortrait(orientation))
{
//Set the array with only 1 view controller
UIViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:currentViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
//Important- Set the doubleSided property to NO.
self.pageViewController.doubleSided = NO;
//Return the spine location
return UIPageViewControllerSpineLocationMin;
}
else
{
NSArray *viewControllers = nil;
ContentViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)currentViewController textContents]];
if(currentIndex == 0 || currentIndex %2 == 0)
{
UIViewController *nextViewController = [self pageViewController:self.pageViewController viewControllerAfterViewController:currentViewController];
viewControllers = [NSArray arrayWithObjects:currentViewController, nextViewController, nil];
}
else
{
UIViewController *previousViewController = [self pageViewController:self.pageViewController viewControllerBeforeViewController:currentViewController];
viewControllers = [NSArray arrayWithObjects:previousViewController, currentViewController, nil];
}
//Now, set the viewControllers property of UIPageViewController
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
return UIPageViewControllerSpineLocationMid;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
//Instantiate the model array
self.modelArray = [[NSMutableArray alloc] init];
self.vcs = [[NSMutableArray alloc]init];
for (int index = 1; index <= 2 ; index++)
{
[self.modelArray addObject:[NSString stringWithFormat:@"Page %d",index]];
}
//Step 1
//Instantiate the UIPageViewController.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
//Step 2:
//Assign the delegate and datasource as self.
self.pageViewController.delegate = self;
self.pageViewController.dataSource = self;
//Step 3:
//Set the initial view controllers.
appDelegate.contentViewController.textContents = [self.modelArray objectAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObjects:appDelegate.firstViewController,appDelegate.contentViewController,nil];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
//Step 4:
//ViewController containment steps
//Add the pageViewController as the childViewController
[self addChildViewController:self.pageViewController];
//Add the view of the pageViewController to the current view
[self.view addSubview:self.pageViewController.view];
//Call didMoveToParentViewController: of the childViewController, the UIPageViewController instance in our case.
[self.pageViewController didMoveToParentViewController:self];
//Step 5:
// set the pageViewController''s frame as an inset rect.
CGRect pageViewRect = self.view.bounds;
pageViewRect = CGRectInset(pageViewRect, 40.0, 40.0);
self.pageViewController.view.frame = pageViewRect;
//Step 6:
//Assign the gestureRecognizers property of our pageViewController to our view''s gestureRecognizers property.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
}
Ah..Finalmente tengo solución para este mismo problema ..., puede ayudarte ...
Cuando configuramos la ubicación de la columna vertebral en UIPageViewControllerSpineLocationMid
, la propiedad de doble doubleSided
de pageViewController se establece automáticamente en YES. Esto significa que el contenido en el frente de la página no se mostrará parcialmente a través de la parte posterior. Pero cuando esta propiedad se establece en NO, el contenido en el frente de la página se mostrará parcialmente a través de la parte posterior, dando a la página un efecto de tipo translúcido. Por lo tanto, en la orientación vertical, tenemos que establecer el valor en NO, de lo contrario, resultaría en una excepción.
Por lo tanto, en su método de delegado UIPageviewcontroller
, en otra parte, agregue esta propiedad de doubleSided
como SÍ cuando devuelva spineLocation como UIPageViewControllerSpineLocationMid
self.pageViewController.doubleSided = YES;
return UIPageViewControllerSpineLocationMid;
El problema es que pasa una matriz que contiene dos controladores de vista al controlador de vista de página, mientras que espera que uno a la vez, cambie su matriz para que sea así:
NSArray *viewControllers = @[appDelegate.firstViewController];
Pasará una de las vistas, pero viewControllerAfterViewController
y viewControllerBeforeViewController
se encargarán del resto.
En lugar de implementar un origen de datos completo, puede configurar el PageViewController con un controlador de vista a la vez cada vez que el usuario presione el botón siguiente o atrás, como
[pageViewController setViewControllers:@[contentViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
Esto animará la transición de la página cuando cambies.
self.pageViewController.doubleSided = NO;
return UIPageViewControllerSpineLocationMid;
Esta es la solución para la excepción.
En xcode se puede encontrar esto.
Vaya a la clase UIPageViewcontroller
y podrá ver la explicación de esto como:
@property (nonatomic, readonly) UIPageViewControllerSpineLocation spineLocation; // If transition style is ''UIPageViewControllerTransitionStylePageCurl'', default is ''UIPageViewControllerSpineLocationMin'', otherwise ''UIPageViewControllerSpineLocationNone''.
// Whether client content appears on both sides of each page. If ''NO'', content on page front will partially show through back.
// If ''UIPageViewControllerSpineLocationMid'' is set, ''doubleSided'' is set to ''YES''. Setting ''NO'' when spine location is mid results in an exception.
@property (nonatomic, getter=isDoubleSided) BOOL doubleSided; // Default is ''NO''.