web-dev-qa-db-ja.com

UIPageViewcontrollerで2つのビューコントローラーを追加する方法

IPadでUIPageViewControllerを使用していますが、最初のページにfirstviewControllerを表示し、横の次のページにContentViewControllerを表示する必要があります。

2つのNSArrayを使用してviewControllersを設定すると、アプリは[self.pagviewController setViewController:]でクラッシュしますが、次の例外があります。

提供されたビューコントローラーの数(2)が、要求されたスパインの場所(UIPageViewControllerSpineLocationMin)に必要な数(1)と一致しません

以下はコードです:

#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;
}
31
user578386

問題は、2つのビューコントローラーを含む配列を一度に1つずつ期待しながらページビューコントローラーに渡すことです。配列を次のように変更します。

NSArray *viewControllers = @[appDelegate.firstViewController];

ビューの1つを渡しますが、viewControllerAfterViewControllerviewControllerBeforeViewControllerが残りを処理します。

23
Ben

ああ..これと同じ問題の解決策がついに得られました..それはあなたを助けるかもしれません。

スパインの場所をUIPageViewControllerSpineLocationMidに設定すると、pageViewControllerのdoubleSidedプロパティが自動的にYESに設定されます。これは、ページ前面のコンテンツが部分的に表示されないことを意味します。ただし、このプロパティがNOに設定されている場合、ページの前面のコンテンツは部分的に透けて見え、ページに半透明の種類の効果を与えます。したがって、縦向きでは、値をNOに設定する必要があります。そうしないと、例外が発生します。

したがって、UIPageviewcontrollerデリゲートメソッドで、他の部分で、spineLocationをdoubleSidedとして返すときに、このUIPageViewControllerSpineLocationMidプロパティをYESとして追加します。

self.pageViewController.doubleSided = YES;
return UIPageViewControllerSpineLocationMid;
2
wesley
self.pageViewController.doubleSided = NO;
return UIPageViewControllerSpineLocationMid;

これが例外の解決策です。

Xcode it selfではこれを見つけることができます。

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'.
0
Mini