¿Cómo agregar un controller de vista nuevo en UIPageViewController después de que se haya tocado el button UIB?

Me preguntaba cómo puedo implementar botones que afectarán el model de UIPageViewController. Por ejemplo, quisiera que mi matriz de models UIPageViewController se cargue con un solo object y cuando se toque un button se agregará un nuevo controller de vista y se volteará automáticamente la página o algo así (como en la aplicación de Notes). Lo mismo para eliminar el object actual que el usuario está viendo.

Hasta ahora, he intentado implementar algunas IBActions en mi controller de vista raíz, pero no he tenido suerte hasta el momento.

Aquí es cómo implemento mi class ViewController:

@implementation ViewController @synthesize modelArray = _modelArray; @synthesize pageVC = _pageVC; #pragma mark - UIPageViewControllerDataSource Methods // Returns the view controller before the given view controller. (requinetworking) - (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. (requinetworking) - (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; } 

¡Muchas gracias!

UIPageViewController utiliza una UIPageViewController datos para get el controller de vista siguiente o anterior. Por lo tanto, la solución es agregar su nuevo controller de vista a la fuente de datos una vez que se toca el button.

Digamos que su fuente de datos se implementa como un NSArray (consulte la plantilla de la aplicación basada en la página de XCode para ver un ejemplo de esto), simplemente agregue su nuevo vc a ese set y establezca el nuevo vc llamando a [UIPageViewController setViewControllers:direction:animated:completion:] .

Como no proporcionó ningún detalle sobre cómo implementó su jerarquía, no puedo ser más específico.

Editar:

Ahora que tengo un código, esto es lo que haría:

Primero, no modelArray la modelArray sino el controller de vista en sí mismo en el modelArray . Además de otras cosas, su layout actual crea una nueva ContentVC cada vez que cambia de página. Eso es una gran cantidad de gastos innecesarios. Así es como implementaría eso:

(por cierto, debería pensar en un nombre más descriptivo que labelContents . En este momento podría estar bien si hay una sola label, pero ¿qué pasa si agrega más tags en el futuro?)

 - (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. (requinetworking) - (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. (requinetworking) - (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; } 

El código en tu comentario:

 - (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); } } 

no funciona porque no estableció la labelContents del ContentVC . Entonces básicamente terminas llamando [self.modelObject indexOfObject:nil] o [self.modelObject indexOfObject:@""] dependiendo de tu implementación de labelContents . Dado que ninguno de ellos está en la matriz, la llamada devuelve NSNotFound que en sistemas de 64 bits se traduce a NSIntegerMax y que es 2147483647 . Más tarde, intenta acceder a su modelArray en el índice NSIntegerMax - 1 y eso genera una NSRangeException .

Así que puede solucionarlo estableciendo la labelContents en su método newButtonTapped: o si sigue mi sugerencia de networkingiseñar su código:

 - (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]; } }