UIPageViewController with different ViewControllers, right way?

拟墨画扇 提交于 2019-12-18 17:33:31

问题


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 (obvious same type of view controller).

But the thing I am finding is that the UIpageviewcontroller is usaully used when you have multiple views of the same type of viewcontroller for example swiping between pictures, you could just set an index in the class and an array of images relating to the index and set it up that way.

But I'm trying to get different view controllers in this set up. Right now it's two but will definitely go up to about 4.

Is UIPageViewController the right way to set it up or something else.

EDIT: Code added below

    //
//  ViewController.m
//  testb
//
#import "MainPostController.h"
#import "MainTableViewController.h"
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize pageViewController;
@synthesize indexValue = _indexValue;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.indexValue= 1;
    NSLog(@"main intitated");

    // Do any additional setup after loading the view, typically from a nib.
    self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"];
    self.pageViewController.dataSource = self;

    MainTableViewController *tvc = [self.storyboard instantiateViewControllerWithIdentifier:@"MainTableViewController"];
    MainPostController *pvc;
    NSArray *viewcontrollers =[NSArray arrayWithObjects:tvc, pvc, nil];

    [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 - 30);

    [self addChildViewController:pageViewController];
    [self.view addSubview:pageViewController.view];
    [self.pageViewController didMoveToParentViewController:self];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}




-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    if (self.indexValue == 1) {
        MainPostController *pvc = [self.storyboard instantiateViewControllerWithIdentifier:@"MainPostController"];
        self.indexValue = 0 ;
        return  pvc;

    }
    else return nil;




}

-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{

    if (self.indexValue == 0) {
        MainTableViewController *tvc = [self.storyboard instantiateViewControllerWithIdentifier:@"MainTableViewController"];
        self.indexValue = 1;
        return tvc;

    }
    else return nil;


}
@end

I want the intial view to be the table view controller(tvc) and i want the Post view controller(pvc) to be to its left. I can load it up and swipe between the two easily but sometime i can swipe further than the boundaries so basically if i start on the tvc-->pvc-->tvc then i can go further by swiping right to the same tvc then the boundary is reached or go the other way tvc-->pvc-->tvc-->pvc-->pvc by swiping left for the last transition. The boundaries are reached in the end. Once the app intially launches at tvc i cannot go forward a page, (which is what should happen) and if i go tvc-->pvc and try to go to a page to the left it wont let me (which is what should happen)

Thanks


回答1:


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!




回答2:


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:




回答3:


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.




回答4:


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.



来源:https://stackoverflow.com/questions/20734673/uipageviewcontroller-with-different-viewcontrollers-right-way

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!