UIPageViewController with different ViewControllers, right way?

后端 未结 4 1254
半阙折子戏
半阙折子戏 2021-01-03 02:25

Basically, I have a Table View Controller and a normal View Controller, I want to make it so that I can swipe between the view controllers like on the home screen of app (ob

相关标签:
4条回答
  • 2021-01-03 03:05

    I had the same issue, here's what i did and working perfectly.

    .h

    @interface ViewController : UIViewController <UIPageViewControllerDataSource>
    
    @property (strong, nonatomic) UIPageViewController *pageViewController;
    
    @property (nonatomic) NSArray *viewControllerIDArr;
    
    @end
    

    .m

    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        [self setupDefaults];
    }
    
    - (void)setupDefaults
    {
        self.viewControllerIDArr = @[@"FirstViewController", @"SecondViewController"];
    
        self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"];
    
        self.pageViewController.dataSource = self;
    
        UIViewController *startingViewController = [self.storyboard instantiateViewControllerWithIdentifier:self.viewControllerIDArr[0]];
    
        NSArray *viewControllers = @[startingViewController];
    
        [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
    
        self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 45);
    
        [self addChildViewController:_pageViewController];
    
        [self.view addSubview:_pageViewController.view];
    
        [self.pageViewController didMoveToParentViewController:self];
    }
    
    - (UIViewController *)getViewControllerFromClass:(Class)class isNext:(BOOL)next
    {
        NSInteger index = [self.viewControllerIDArr indexOfObject:[NSString stringWithFormat:@"%@", class]];
    
        if (next)
            index+=1;
        else
            index-=1;
    
        if (index < 0 || index >= self.viewControllerIDArr.count)
            return nil;
        else
            return [self.storyboard instantiateViewControllerWithIdentifier:self.viewControllerIDArr[index]];
    
    }
    
    
    #pragma mark - Page View Controller Data Source
    
    - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
    {
        return [self getViewControllerFromClass:viewController.class isNext:NO];
    }
    
    - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
    {
        return [self getViewControllerFromClass:viewController.class isNext:YES];
    }
    
    - (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
    {
        return 0;
    }
    
    - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
    {
        return 0;
    }
    

    Note:

    self.viewControllerIDArr containers Storyboard ID's of the viewControllers.

    It looks like this in storyboard:

    0 讨论(0)
  • 2021-01-03 03:10

    You could use a UIViewPageViewController, with some custom logic.

    As you say, the normal way to handle this is to have the page view controller's data source simply create the same type of view controller for each page and fill it with data from your model.

    In your case, you could add a pageNumber property to all the view controllers that you're going to host in your page view controller. Then, in the data source methods, use the page number of the old view controller to figure out the new page number. Then have a switch statement based on page number. Each case in the switch statement would create a different type of view controller.

    0 讨论(0)
  • 2021-01-03 03:11

    This is an old question but since I bumped into this problem I'll post my solution.

    The first time I did this I added my code

    func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { }
    

    Which received problems when you continuously scroll the views using two fingers and didFinishAnimating is not called unless scrolling stops.

    So I just used this delegate method instead.

    func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) {
    
        let currentView = pendingViewControllers[0]
    
        if currentView is UINavigationController && currentView.restorationIdentifier == "Settings" {
            index = 0
        } else if currentView is UINavigationController && currentView.restorationIdentifier == "Main" {
            index  = 1
        } else if currentView is UINavigationController && currentView.restorationIdentifier == "Message" {
            index = 2
        }
    }
    

    Where currentView is the currentUIViewController (or UINavigationController like what I am using, using a restorationIdentifier to identify my navigation controller as well), and index is a global value to know which UIViewController in the array to instantiate.

    0 讨论(0)
  • 2021-01-03 03:23

    Finally done it, didn't have to add any properties to the different classes. Just tested the class. Heres the code:

    -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
    {
        if ([viewController isKindOfClass:[MainTableViewController class]]) {
            MainPostController *pvc = [self.storyboard instantiateViewControllerWithIdentifier:@"MainPostController"];
            return  pvc;
    
        }
    
        else return nil;
    
    }
    
    
    -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
    {
    
        if ([viewController isKindOfClass:[MainPostController class]]) {
            MainTableViewController *tvc = [self.storyboard instantiateViewControllerWithIdentifier:@"MainTableViewController"];
            return tvc;
    
        }
        else return nil;
    }
    

    Should be easy to add more view controllers as i just need to add else if statements to test them. The main problem solver was the method isKindOfClass:

    Thanks for your reply guys!

    0 讨论(0)
提交回复
热议问题