Как добавить два контроллера представления в UIPageViewcontroller
Я использую UIPageViewController
на iPad, где мне нужно показать firstviewController
на первой странице и ContentViewController
на следующей странице в альбомной ориентации.
Если я установил NSArray
с двумя viewControllers
, приложение выйдет из строя в [self.pagviewController setViewController:]
со следующим исключением:
Количество предоставленных контроллеров представления (2) не соответствует требуемому числу (1) для запрашиваемого местоположения позвоночника (UIPageViewControllerSpineLocationMin)
Ниже приведен код:
#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 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 gestureRecognizers property.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
}
Ответы
Ответ 1
Проблема заключается в том, что вы передаете массив, содержащий два контроллера представления, в контроллер просмотра страниц, когда он ожидает по одному, измените свой массив следующим образом:
NSArray *viewControllers = @[appDelegate.firstViewController];
Вы пройдете одно из видов, но viewControllerAfterViewController
и viewControllerBeforeViewController
будут обрабатывать остальные.
Ответ 2
Ah..Наконец получил решение для этой же проблемы.., это может помочь вам.
Когда мы устанавливаем местоположение позвоночника на UIPageViewControllerSpineLocationMid
, свойство doubleSided
для pageViewController автоматически устанавливается на YES. Это означает, что содержимое на странице не будет отображаться частично назад. Но когда для этого свойства установлено значение НЕТ, содержимое на лицевой панели частично показывается через спину, придавая странице полупрозрачный вид эффекта. Итак, в портретной ориентации мы должны установить значение NO, иначе это приведет к исключению.
Итак, в вашем делегаторе UIPageviewcontroller
, иначе добавьте это свойство doubleSided
как ДА, когда вы вернете spineLocation как UIPageViewControllerSpineLocationMid
self.pageViewController.doubleSided = YES;
return UIPageViewControllerSpineLocationMid;
Ответ 3
self.pageViewController.doubleSided = NO;
return UIPageViewControllerSpineLocationMid;
Это решение для исключения.
В xcode вы можете найти это.
Перейдите в класс UIPageViewcontroller
там, где вы можете увидеть объяснение для этого:
@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'.
Ответ 4
Вместо того, чтобы внедрять полный источник данных, вы можете установить PageViewController с одним контроллером представления каждый раз, когда пользователь нажимает кнопку "Следующий" или "Назад", например
[pageViewController setViewControllers:@[contentViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
Это приведет к оживлению перехода страницы при переключении.