Removing a view controller from UIPageViewController

前端 未结 12 2537
梦谈多话
梦谈多话 2020-11-28 19:22

It\'s odd that there\'s no straightforward way to do this. Consider the following scenario:

  1. You have a page view controller with 1 page.
  2. Add another p
12条回答
  •  刺人心
    刺人心 (楼主)
    2020-11-28 19:46

    I had a similar situation where I wanted the user to be able to "tap and delete" any page from the UIPageViewController. After playing a bit with it, I found a simpler solution than the ones described above:

    1. Capture the page index of the "dying page".
    2. Check to see if the "dying page" is the last page.
      • This is important because if it is the last page, we need to scroll left (if we have pages "A B C" and delete C, we will scroll to B).
      • If it is not the last page, we will scroll right (if we have pages "A B C" and delete B, we will scroll to C).
    3. Make a temporary jump to a "safe" place (ideally the final one). Use animated: NO to have this happen instantaneously.

      UIViewController *jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex-1];
      [self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
      
    4. Delete the selected page from the model/datasource.

    5. Now, if it is the last page:

      • Adjust your model to select the page on the left.
      • Get the viewcontroller on the left, note that THIS IS THE SAME ONE than the one you retrieved in step 3.
      • It is important to do this AFTER you have deleted the page from the datasource because it will refresh it.
      • Jump to it, this time with animated: YES.

        jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex-1];
        [self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
        
    6. In the case where it was NOT the last page:

      • Adjust your model to select the page on the right.
      • Get the viewcontroller on the right, note that this is not the one you retrieved in step 3. In my case, you will see that it is the one at dyingPageIndex, because the dying page has already been removed from the model.
      • Again, it is important to do this AFTER you have deleted the page from the datasource because it will refresh it.
      • Jump to it, this time with animated: YES.

        jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex;
        [self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
        
    7. That's it! This works well in XCode 6.1.1.

    Full code below. This code is in my UIPageViewController and is called through a delegate from the page to be deleted. In my case, deleting the first page was not allowed as it contains different things from the rest of the pages. Of course, you need to substitute:

    • YourUIViewController: with the class of your individual pages.
    • YourTotalNumberOfPagesFromModel: with the total number of pages in your model
    • [YourModel deletePage:] with the code to delete the dying page from your model

      - (void)deleteAViewController:(id)sender {
          YourUIViewController *dyingGroup = (YourUIViewController *)sender;
          NSUInteger dyingPageIndex = dyingGroup.pageIndex;
          // Check to see if we are in the last page as it's a special case.
          BOOL isTheLastPage = (dyingPageIndex >= YourTotalNumberOfPagesFromModel.count);
          // Make a temporary jump back - make sure to use animated:NO to have it jump instantly
          UIViewController *jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex-1];
          [self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
          // Now delete the selected group from the model, setting the target
          [YourModel deletePage:dyingPageIndex];
          if (isTheLastPage) {
              // Now jump to the definitive controller. In this case, it's the same one, we're just reloading it to refresh the data source.
              // This time we're using animated:YES
              jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex-1];
              [self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
          } else {
              // Now jump to the definitive controller. This reloads the data source. This time we're using animated:YES
              jumpToAnotherViewController = [self viewControllerAtIndex:dyingPageIndex];
              [self setViewControllers:@[jumpToAnotherViewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
          }
      }
      

提交回复
热议问题