我在iPad上使用UIPageViewController
,我需要在第一页显示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'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;
}
答案 0 :(得分:22)
问题是您将包含两个视图控制器的数组传递给页面视图控制器,而它一次只需要一个,将数组更改为:
NSArray *viewControllers = @[appDelegate.firstViewController];
您将传递其中一个视图,但viewControllerAfterViewController
和viewControllerBeforeViewController
将处理其余视图。
答案 1 :(得分:1)
啊......最终得到了同样问题的解决方案......,它可能对你有帮助..
当我们将脊椎位置设置为UIPageViewControllerSpineLocationMid
时,pageViewController的doubleSided
属性会自动设置为YES。这意味着页面前面的内容不会部分显示回来。但是当此属性设置为NO时,页面前面的内容将部分显示回来,使页面具有半透明效果。因此,在纵向方向上,我们必须将值设置为NO,否则会导致异常。
因此,在UIPageviewcontroller
委托方法中,在其他部分中,当您将spineLocation作为doubleSided
UIPageViewControllerSpineLocationMid
属性添加为YES
self.pageViewController.doubleSided = YES;
return UIPageViewControllerSpineLocationMid;
答案 2 :(得分:0)
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'.
答案 3 :(得分:-2)
每次用户按下一个或后一个按钮时,您可以一次设置一个视图控制器,而不是实现完整的数据源,例如
[pageViewController setViewControllers:@[contentViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
这将在您切换时为页面转换设置动画。