UIScrollView contains multiple TableViews with pagingEnabled - ios

I have an UIScrollView that contains 3 UITableView and pagingEnabled = YES.
Users can pan to the left or right to switch between tables (just like the Notification Center of iOS).
I've handled almost all visual bugs (i can help if anyone needed), but the problem is every table have an UISearchBar. Which means in my controller, I've to create 3 UITableView, 3 UISearchBar and 3 UISearchDisplayController.
That will be one of a hell messy controller.
What the best practice in this case ?

It does sound tedious.
Why not create a single UIViewController having a SearchBar and a Tableview. Customize your viewController to be differentiated by tags, add some delegates probably and add it to your UIScrollview? That way, the coding will be structured and clean
I'm just spitballing though.

left or right table will move with your swipe. You have 1 class of your custom UIViewController but different instances.
- (SearchResultViewController *)viewControllerAtIndex:(NSUInteger)index
{
if (([[LeboncoinAgent shareAgent].searchConditions count] == 0) || (index >= [[LeboncoinAgent shareAgent].searchConditions count])) {
return nil;
}
// Create a new view controller and pass suitable data.
SearchResultViewController *pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SearchResultViewControllerId"];
pageContentViewController.pageIndex = index;
pageContentViewController.controller = self;
return pageContentViewController;
}
#pragma mark - Page View Controller Data Source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = ((SearchResultViewController*) viewController).pageIndex;
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
_currentPageIndex = index;
return [self viewControllerAtIndex:index];
}

Related

How do I create variable number of ViewControllers within a PageViewController?

I have a UIPageViewController in a container that is supposed to show, at minimum, three pages; at maximum, six. The number of pages would be determined by the user before the PageViewController appears.
For a bigger picture, I'm trying to create a project management application that allows for an agile ticket creating and management system. The PageVC is supposed to flip through 3 to 6 columns depending on how many the user wants to go along with that project. As an example, if it's a simple project, they can just have three columns named: "Unassigned", "Assigned", and "Complete". More complex projects could, for example, have 5 columns, named: "Backlog", "Issues", "In Progress", "Review", "Done". Each one of those columns would have its own ViewController within the PageVC.
This is what my data model looks like, to get an idea of where I get the number of columns from (Project attribute named: "projectColumnCount"):-
you can use following ObjectiveC concept in Swift.
It is Advisable to create a content view controller initially and then to use Pageviewcontroller Delegate Methods to create other controllers.
you can check following delegate Methods of Pageviewcontroller for same
Delegate Methods for Pageviewcontroller are as below.
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = ((PageContentViewController*) viewController).pageIndex;
if ((index == 0) || (index == NSNotFound)) {
return nil;
} index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = ((PageContentViewController*) viewController).pageIndex;
if (index == NSNotFound)
{
return nil;
}
index++;
if (index == [arrPage count]) {
return nil;
}
return [self viewControllerAtIndex:index];
}
you can use below method to create instance of ContentVC
- (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index
{
if (([arrPage count] == 0) || (index >= [arrPage
count])) {
return nil;
}
// Create a new view controller and pass suitable data.
pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageContentViewController"];
pageContentViewController.delagate = self;
pageContentViewController.pageIndex = index;
pageContentViewController.collselectedType = selectedType;
return pageContentViewController;
}
you can also Create Array of contentVC and can set that in Pageviewcontroller but it will consume more memory
you can set view conteollers array as below.
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];

How to conditionally go to the next page in pageViewController?

I am using pageViewController in my App. I have 9 pages which are created dymanically and each page have 1 question which have 4 multiple choice answers. Each option have custom UIButton with image and its "BlankedCheckBox" when the option is not selected and "MakredCheckBox" when its selected. Right now I can go to next page even if any of the available answer is not selected. I want to go to the next page only if user has selected one of the available option. The transition style of my pageViewController is scroll.
It seems to me like I have to add something in following method. Any help would be greatly appreciated, thanks.
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = ((PageContentViewController *) viewController).pageIndex;
if (index == NSNotFound) {
return nil;
}
index ++;
if (index == [self.questionTitles count]) {
return nil;
}
return [self viewControllerAtIndex:index];
}
You should not implement the dataSource methods. If you do the user can scroll using a gesture.
To achieve the behavior you want, set the page in code in the IBAction of the control:
- (IBAction)nextPage {
[self setViewControllers:[nextViewController]
direction: UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
}

How should I pass data between UIViewControllers in UIPageViewController and save variables

I am having trouble figuring out how to save/pass data between UIViewControllers in UIPageViewController. My setup is like so:
#pragma mark - UIPageViewControllerDataSource
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
//This is nice and avoids having to use a counter
NSString *vcRestorationID = viewController.restorationIdentifier;
NSUInteger index = [self.controllerRestorationIDs indexOfObject:vcRestorationID];
if (index == 0) {
return nil;
}
return [self viewControllerAtIndex:index - 1];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSString *vcRestorationID = viewController.restorationIdentifier;
NSUInteger index = [self.controllerRestorationIDs indexOfObject:vcRestorationID];
//Don't allow it to go forward if there is one at the end
if (index == self.controllerRestorationIDs.count - 1) {
return nil;
}
return [self viewControllerAtIndex:index + 1];
}
#pragma mark - Private Methods
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
// Only process a valid index request.
if (index >= self.controllerRestorationIDs.count) {
return nil;
}
// Create a new view controller.
//Note this is just an extension of UIViewController with a variable inside. All my view controllers in this must be subclassed off BaseContentViewController
BaseContentViewController *contentViewController = (BaseContentViewController *)[self.storyboard instantiateViewControllerWithIdentifier:self.controllerRestorationIDs[index]];
// Set any data needed by the VC here
contentViewController.rootViewController = self;
return contentViewController;
}
This is in my RootViewController.m (the controller that contains UIPageViewController). What I need to be able to do is so save a variable or data in the current displayed controller when a new one is swiped to. Do I need to use a singleton or something for this?
Try to use NSNotificationCenter class in your *ViewController(s)
NSNotificationCenter will probably be your fastest implementation if you only ever have to pass small pieces of information back and forth and need to do so to multiple destinations simultaneously. If, in the far more likely instance, you need to update information frequently and reference it only when necessary then a singleton would be a much more practical solution.
Singletons are surprisingly easy to use and implement. A quick google search had this walkthrough as the first result. That will show you how to set it up, and using it is very similar to using any other property in a view controller.
It may take a couple extra minutes of work to get running over NSNotificationCenter but it's more extensible, readable, and maintainable.

UIPageViewController and saving the state of the UIViewControllers

I am pretty new to UIPageViewControllers. I have setup one that can page through different types of UIViewControllers.
I have noticed that when I scroll back to a previous one all the data and states are reset (i.e. I previously changed the UIViewController background color and it has reset back to default). I am using restoration IDs from the story board to initiate these controllers.
If I am using these shouldn't it save the state of the controller?
Code for changing controllers:
#pragma mark - UIPageViewControllerDataSource
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
//This is nice and avoids having to use a counter
NSString *vcRestorationID = viewController.restorationIdentifier;
NSUInteger index = [self.controllerRestorationIDs indexOfObject:vcRestorationID];
if (index == 0) {
return nil;
}
return [self viewControllerAtIndex:index - 1];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSString *vcRestorationID = viewController.restorationIdentifier;
NSUInteger index = [self.controllerRestorationIDs indexOfObject:vcRestorationID];
//Don't allow it to go forward if there is one at the end
if (index == self.controllerRestorationIDs.count - 1) {
return nil;
}
return [self viewControllerAtIndex:index + 1];
}
#pragma mark - Private Methods
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
// Only process a valid index request.
if (index >= self.controllerRestorationIDs.count) {
return nil;
}
// Create a new view controller.
BaseContentViewController *contentViewController = (BaseContentViewController *)[self.storyboard instantiateViewControllerWithIdentifier:self.controllerRestorationIDs[index]];
// Set any data needed by the VC here
contentViewController.rootViewController = self;
return contentViewController;
}
Is there a way to do this so the state is saved and the controllers aren't reloaded every time?
This behavior happens because you instanciate a new view controller each time you access it.
To solve this :
you can cache the view controllers : store them in a global mutable array of your page view controller, and check each time the page view controller asks its data source for a view controller, add it to the global array or retrieve it if it's already in there.
use class variables instead of instance variables for the properties you change in the view controllers.
The first solution is volatile : whenever the pageVC is deallocated, you'll lose the modification made to the view controllers. The second one is more sure.

how to pass data in UIPageViewController in ios [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
i am new to Xcode.
i want to create a app with Single view with UIPageViewController .
In this its have 5 screen.
First screen have a textfield and second screen have label and textfield and so on.
when user enter a text in textfield and scroll then textfield data (means text) of first
screen to second screen label and so on.
please tell me the answer i searched every where on next even stackoverflow.com and nothing
found like that.
please help me.
first take a UIPageViewController and set storyboard ID in IB and one otherview controller which is a simple UIViewController but remember its name as a PageContentViewController i.e., this viewcontroller holds the 5 viewcontrollers u want to show.
in PageContentViewController class declare a UIPageViewController *pageViewController;
and in viewWillAppear: initialise it with its storyboardID like this
pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"storyboardID"];
then import the 5 viewcontroller classes into this PageViewController class and create objects for it like this
#import "ViewController1";
#import "ViewController2";
#import "ViewController3";
#import "ViewController4";
#import "ViewController5";
and in interface create objects
ViewController1 *vcObj1;
ViewController2 *vcObj2;
ViewController3 *vcObj3;
ViewController4 *vcObj4;
ViewController5 *vcObj5;
and now in .m file set these 5 viewcontrollers as an objects in an array in viewWillAppear: method like this
[self setViewControllers:#[vcObj1, vcObj2, vcObj3, vcObj4, vcObj5]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];
[self addChildViewController:_pageViewController];
[self.view addSubview:_pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
now u have to set pageviewcontroller delegate to the pagecontentviewcontroller class and write the delegate methods in .m file
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = ((PageContentViewController*) viewController).pageIndex;
if ((index == 0) || (index == NSNotFound)) {
return vcObj1;
}
else if(index == 1) {
return vcObj2;
}
else if(index == 2) {
return vcObj3;
}
else if(index == 3){
return vcObj4;
}
else if(index == 4) {
return vcObj5;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = ((PageContentViewController*) viewController).pageIndex;
if (index == NSNotFound) {
return nil;
}
index++;
if (index == 0) {
return vcObj5;
}
else if(index == 1) {
return vcObj4;
}
else if(index == 2) {
return vcObj3;
}
else if(index == 3){
return vcObj2;
}
else if(index == 4) {
return vcObj1;
}
index++;
return [self viewControllerAtIndex:index];
}
if u have written these two delegates method correctly ur functionality is done because these two are the major ones totally controlling the pageviewcontroller. i'm not sure about the indexes, just trial it once and change the indexes according to ur requirement.
Happy coding

Resources