4

UIPageViewControllerのモデルに影響を与えるボタンをどのように実装できるのか疑問に思いました。たとえば、UIPageViewControllerモデル配列に単一のオブジェクトをロードし、ボタンをタップすると、新しいView Controllerが追加され、ページなどが自動的にめくります(メモアプリなど)。ユーザーに表示されている現在のオブジェクトを削除する場合も同様です。

これまでのところ、ルートビューコントローラーにいくつかのIBActionを実装してみましたが、今のところうまくいきません。

ViewControllerクラスを実装する方法は次のとおりです。

@implementation ViewController

@synthesize modelArray = _modelArray;
@synthesize pageVC = _pageVC;

#pragma mark - UIPageViewControllerDataSource Methods

// Returns the view controller before the given view controller. (required)
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
      viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentVC *)viewController     labelContents]];
    if(currentIndex==0)
        return nil;

    ContentVC *cVC = [[ContentVC alloc] init];
    cVC.labelContents = [self.modelArray objectAtIndex:currentIndex-1];
    return cVC;
}

// Returns the view controller after the given view controller. (required)
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
   viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentVC *)viewController labelContents]];
    if(currentIndex==self.modelArray.count-1)
        return nil;

    ContentVC *cVC = [[ContentVC alloc] init];
    cVC.labelContents = [self.modelArray objectAtIndex:currentIndex+1];
    return cVC;
}

#pragma mark - UIPageViewControllerDelegate Methods
// Returns the spine location for the given orientation.
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
               spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
    if(UIInterfaceOrientationIsPortrait(orientation)){
        // Set the array with only 1 view controller
        UIViewController *currentVC = [self.pageVC.viewControllers objectAtIndex:0];
        NSArray *viewControllers = [NSArray arrayWithObject:currentVC];
        [self.pageVC setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

        // Set the doubleSided property to NO
        self.pageVC.doubleSided = NO;
        // Return the spine location
        return UIPageViewControllerSpineLocationMin;
    } else { // if landscape
        NSArray *viewControllers = nil;
        ContentVC *currentVC = [self.pageVC.viewControllers objectAtIndex:0];
        NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentVC *)viewControllers labelContents]];
        if(currentIndex==0 || currentIndex %2 == 0){
            UIViewController *nextViewController = [self pageViewController:self.pageVC viewControllerAfterViewController:currentVC];
            viewControllers = [NSArray arrayWithObjects:currentVC, nextViewController, nil];
        } else {
            UIViewController *previousVC = [self pageViewController:self.pageVC viewControllerBeforeViewController:currentVC];
            viewControllers = [NSArray arrayWithObjects:previousVC, currentVC, nil];
        }
        // Set the view controllers as property of the UIPageViewController
        [self.pageVC setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
        return UIPageViewControllerSpineLocationMid;
    }

}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Instantiate the model array
    self.modelArray = [[NSMutableArray alloc] init];
    [self.modelArray addObject:@"Page One"];
    NSLog(@"%@", self.modelArray);

    // Instantiate the UIPageViewController
    self.pageVC = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];

    // Assign the delegate and datasource as self
    self.pageVC.delegate = self;
    self.pageVC.dataSource = self;

    // Set the initial view controllers
    ContentVC *cVC = [[ContentVC alloc] initWithNibName:@"ContentVC" bundle:nil];
    cVC.labelContents = [self.modelArray objectAtIndex:0];
    NSArray *viewControllers = [NSArray arrayWithObject:cVC];
    [self.pageVC setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];

    // Add the pageViewController as the childViewController
    [self addChildViewController:self.pageVC];

    // Add the view of pageViewController  to the currentView
    [self.view addSubview:self.pageVC.view];

    // Call didMoveToParentViewController: of the childViewController, the UIPageViewController instance in our case.
    [self.pageVC didMoveToParentViewController:self];

    // Assign the gestureRecognizers property of the pageViewController to the view's gestureRecognizers property
    self.view.gestureRecognizers = self.pageVC.gestureRecognizers;

}

どうもありがとうございます!

4

1 に答える 1

11

UIPageViewControllerデータソースを使用して、次または前のViewControllerを取得します。したがって、解決策は、ボタンに触れたら、新しいViewControllerをデータソースに追加することです。

データソースがとして実装されているとしNSArrayましょう(この例については、XCodeのページベースのアプリケーションテンプレートを参照してください)。新しいvcをその配列に追加し、を呼び出して新しいvcを設定し[UIPageViewController setViewControllers:direction:animated:completion:]ます。

階層をどのように実装したかについての詳細を提供しなかったので、これ以上具体的にすることはできません。

編集:

コードができたので、次のようにします。

まず、保存するのlabelContentsではなく、ViewController自体をに保存しmodelArrayます。他のものに加えて、現在のデザインは、ContentVCページを変更するたびに新しいものを作成します。これは多くの不要なオーバーヘッドです。これを実装する方法は次のとおりです。

(ところで、よりわかりやすい名前を考える必要がありますlabelContents。現在、ラベルが1つしかない場合は問題ないかもしれませんが、将来さらにラベルを追加するとどうなりますか?)

- (ContentVC *)contentViewControllerWithLabelContents:(NSString *)labelContents
{
    ContentVC *vc = [[ContentVC alloc] initWithNibName:@"ContentVC" bundle:nil];
    vc.labelContents = labelContents;
    return vc;
}

- (void)viewDidLoad
{
    NSMutableArray *vcs = [NSMutableArray array];
    [vcs addObject:[self contentViewControllerWithLabelContents:@"Page One"]];
    [vcs addObject:[self contentViewControllerWithLabelContents:@"Page Two"]];
    //...
    self.modelArray = vcs;
}


#pragma mark - UIPageViewControllerDataSource Methods

// Returns the view controller before the given view controller. (required)
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
      viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger currentIndex = [self.modelArray indexOfObject:viewController];
    if(currentIndex == 0)
        return nil;

    ContentVC *cVC = [self.modelArray objectAtIndex:currentIndex - 1];
    return cVC;
}

// Returns the view controller after the given view controller. (required)
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
   viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger currentIndex = [self.modelArray indexOfObject:viewController];
    if(currentIndex == self.modelArray.count - 1)
        return nil;

    ContentVC *cVC = [self.modelArray objectAtIndex:currentIndex + 1];
    return cVC;
}

コメントのコード:

- (IBAction)newButtonTapped:(id)sender 
{ 
    if(sender){ 
        [self.modelArray addObject:@"Page Two"]; 
        ContentVC *newVC = [[ContentVC alloc] initWithNibName:@"ContentVC" bundle:nil]; 
        NSArray *arr = [NSArray arrayWithObject:newVC]; 
        [self.pageVC setViewControllers:arr direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; 
        NSLog(@"%@", self.modelArray); 
    } 
}

labelContentsのを設定しなかったため、機能しませんContentVC。したがって、基本的には、の実装に応じて呼び出す[self.modelObject indexOfObject:nil]か、依存することになります。どちらも配列に含まれていないため、呼び出しは64ビットシステムでどちらに変換されるかを返します。これはです。後であなたはあなたのatインデックスにアクセスしようとします、そしてそれはを上げます。[self.modelObject indexOfObject:@""]labelContentsNSNotFoundNSIntegerMax2147483647modelArrayNSIntegerMax - 1NSRangeException

labelContentsしたがって、newButtonTapped:メソッドでを設定するか、私の提案に従ってコードを再設計することで、これを修正できます。

- (IBAction)newButtonTapped:(id)sender 
{ 
    if(sender){ 
        ContentVC *newVC = [self contentViewControllerWithLabelContents:@"Page Two"]; 
        [self.modelArray addObject:newVC];

        NSArray *newVCs = nil;

        if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation) || self.modelArray.count == 1)
            newVCs = @[newVC];
        else
        {
            NSUInteger secondLastIndex = self.modelArray.count - 2;
            id previousVC = [self.modelArray objectAtIndex:secondLastIndex];
            newVCs = @[previousVC, newVC];
        }

        [self.pageVC setViewControllers:newVCs direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
    } 
}
于 2012-11-04T22:37:44.293 に答える