How to remove the bottom gap of UIPageViewController - ios

I am using UIPageViewController to show images full screen, the UIViewController which is added to UIPageController as a sub view / child has the images being showed using ImageView.
Problem is the images arent comming fullscreen, instead the pagecontrol view's donts are appearing at the bottom and that space is completely wasted. Please check the image attached.
Here is the code
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
[[self.pageController view] setFrame:[[self view] bounds]];
NewsItemViewController *initialViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageController];
[[self view] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];
Here NewsItemViewController is UIViewController showing images and some text and The MainViewController implements UIPageViewControllerDataSource protocol and necessary methods in MainViewController.
I believe there has to be a way to do show the things in full screen.
*** Also the MainViewController is a part of a storyboard if that matters.

Finally got the solution myself I just hide the page control from UIViewPageController and then extended the size of the UIPageViewController to cover up the gap left due to absense of page control.
NSArray *subviews = self.pageController.view.subviews;
UIPageControl *thisControl = nil;
for (int i=0; i<[subviews count]; i++) {
if ([[subviews objectAtIndex:i] isKindOfClass:[UIPageControl class]]) {
thisControl = (UIPageControl *)[subviews objectAtIndex:i];
}
}
thisControl.hidden = true;
self.pageController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height+40);

Curious. The docs say:
If both of the methods in “Supporting a Page Indicator” are
implemented and the page view controller’s transition style is
UIPageViewControllerTransitionStyleScroll, a page indicator is
visible.
Those two methods are:
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
}
Are you implementing these two data source methods? If so, perhaps if you remove them you won't have to manually remove the page control (dots)? A quick test would be to change the
UIPageViewControllerTransitionStyleScroll
to
UIPageViewControllerTransitionStylePageCurl
and see if the page control indicator dots go away. (After commenting out your hide method, of course.)

UIPageViewController dots are only shown when you have implemented following method:
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController;
check in you code. and also returning back zero in this method will hide the dots (UIPageControl)

I am adding for swift 2.2 compatible code
for view in self.view.subviews {
if view.isKindOfClass(UIScrollView) {
view.frame = UIScreen.mainScreen().bounds
} else if view.isKindOfClass(UIPageControl) {
view.backgroundColor = UIColor.clearColor()
}
}
This is the Swift 4 compatible solution, embedded in viewDidLayoutSubviews
for view in self.view.subviews {
if view.isKind(of:UIScrollView.self) {
view.frame = UIScreen.main.bounds
} else if view.isKind(of:UIPageControl.self) {
view.backgroundColor = UIColor.clear
}
}

Swift version :). Return Zero for below implementation inside UIPageViewController subclass.
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int { return 0 }
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int { return 0 }

Set your pager controller as so
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
[[self.pageController view] setFrame:[[self view] bounds]];
And implement,this method should return any value greater than 1
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
// The selected item reflected in the page indicator.
return 2;
}
Now the gap at the bottom space is removed and no page control shown :)

Related

UIPageControl Current page indicator switches before new view is presented

I have implemented a niceUIPageViewControl with aPageControl. When swiping the indicator changes and shows the correct current page.
However i noticed that all that it takes for the current page indicator to switch is to start swiping. Meaning if i start swiping but then let go of the finger the current page indicator has switched like the page has been switched however it has not. This is the code that i am using to make the switch:
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
NSUInteger index = [self.navigationController.viewControllers indexOfObject:viewController];
self.pageControl.currentPage = index;
}
Another thing i noticed was that when i swipe right and left changing views FAST the page indicator is just stuck and does not move.
So it only works when you are not changing views fast. If you need any additional code let me know. Thank you.
Edit
This is the code i use to implement my UIPageViewController.
- (void)viewDidLoad
{
[super viewDidLoad];
// Create the data model
self.navigationItem.title = #"Tabell";
self.identifiers = [[NSMutableArray alloc] init];
[self.identifiers addObject:#"rankTable"];
[self.identifiers addObject:#"page2"];
// Create page view controller
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
self.pageViewController.dataSource = self;
self.pageViewController.delegate = self;
self.navigationController.delegate = self;
CGSize navBarSize = self.navigationController.navigationBar.bounds.size;
CGPoint origin = CGPointMake( navBarSize.width/2, navBarSize.height/2 );
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(origin.x, origin.y+16,
0, 0)]; //Here added 45 to Y and it did the trick
self.pageControl.pageIndicatorTintColor = navbarColor;
self.pageControl.currentPageIndicatorTintColor = [UIColor lightGrayColor];
[self.pageControl setNumberOfPages:2];
[self.navigationController.navigationBar addSubview:self.pageControl];
UITableViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
CGFloat tabBarHeight = self.tabBarController.tabBar.frame.size.height;
// Change the size of page view controller
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - tabBarHeight);
[self addChildViewController:_pageViewController];
[self.view addSubview:_pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
}
Why don't you implement the UIPageViewControllerDelegate's
- pageViewController: didFinishAnimating: previousViewControllers: transitionCompleted: method? It has a transitionCompleted boolean which tells you if you should update your page control. Your current implementation seems to be buggy because as soon as you star swiping a page, it loads a view controller for the next page and calls the ...didShow... method. Hope this hepls.

Can we customize the page indicator in UIPageViewController?

Now it's white dots with black background. What about if I want it to be black dots with white backgrounds?
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0)
{
return _imageArrays.count;
}// The number of items reflected in the page indicator.
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0)
{
return self.intCurrentIndex;
}// The selected item reflected in the page indicator.
You can use UIAppearance to change the color of UIPageControl. Try this in your AppDelegate's didFinishLaunchingWithOptions function.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
pageControl.currentPageIndicatorTintColor = [UIColor blackColor];
pageControl.backgroundColor = [UIColor blueColor];
return YES;
}
EDIT:
To apply style only to a particular view controller, use appearanceWhenContainedIn instead, as following:
UIPageControl *pageControl = [UIPageControl appearanceWhenContainedIn:[MyViewController class], nil];
Now, only UIPageControl objects contained in the MyViewController are going to adapt this style.
Thanks Mike & Shingoo!
EDIT:
If you see black background around UIPageControl at the bottom of your screen, it is due to the background color of your UIPageViewController not UIPageControl. You can change this color as following:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor]; //Set it to whatever you like
}
I don't believe that you can manipulate the UIPageViewController's page control. My solution:
I have a "root" UIViewController that is UIPageViewControllerDelegate and UIPageViewControllerDataSource.
On this root view controller, I have #property (strong, nonatomic) IBOutlet UIPageControl *pageControl. In the corresponding storyboard nib, I add a UIPageControl, position it, and check "Hides for Single Page". I can also change the colors, if I wish.
Then, I add the following in the root view controller's viewDidLoad: self.pageControl.numberOfPages = [self.features count]
My root view controller also has #property (strong, nonatomic) UIPageViewController *pageViewController. And in the implementation:
self.pageViewController = [[UIPageViewController alloc]
initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:nil];
self.pageViewController.delegate = self;
DataViewController *startingViewController = [self viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];
self.pageViewController.dataSource = self;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
self.pageViewController.view.frame = CGRectMake(0.0, 0.0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height + 10.0);
[self.pageViewController didMoveToParentViewController:self];
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
(SIDE NOTE: That line that sets the frame makes the height of the UIPageViewController's view exceed the screen size so that the native page control is no longer visible. My app is portrait only, iPhone only, so I got off a bit easy here. If you need to handle rotations, you'll have to find a way to keep that native page control offscreen. I tried using auto layout, but UIPageViewController creates a set of magic views that have a bunch of autolayout mask constraints that I couldn't find a way to override.)
Anyway...then I add an extra UIPageViewController delegate method to change my new, non-native UIPageControl to the currently-selected page:
- (void)pageViewController:(UIPageViewController *)viewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
if (!completed){return;}
// Find index of current page
DataViewController *currentViewController = (DataViewController *)[self.pageViewController.viewControllers lastObject];
NSUInteger indexOfCurrentPage = [self indexOfViewController:currentViewController];
self.pageControl.currentPage = indexOfCurrentPage;
}
Not as pretty as I would like, but Apple's API for this class doesn't exactly lend itself to elegance.
You can actually grab it and store it locally in your own property in one of the delegate calls.
Put this code inside your delegate to access the UIPageControl inside the UIPageViewController:
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
[self setupPageControlAppearance];
return kPageCount;
}
- (void)setupPageControlAppearance
{
UIPageControl * pageControl = [[self.view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(class = %#)", [UIPageControl class]]] lastObject];
pageControl.pageIndicatorTintColor = [UIColor grayColor];
pageControl.currentPageIndicatorTintColor = [UIColor blackColor];
}
You can recursively search it in your subviews
- (void)findAndConfigurePageControlInView:(UIView *)view
{
for (UIView *subview in view.subviews) {
if ([subview isKindOfClass:[UIPageControl class]]) {
UIPageControl * pageControl = (UIPageControl *)subview;
//customize here
pageControl.hidesForSinglePage = YES;
break;
} else {
[self findAndConfigurePageControlInView:subview];
}
}
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
[self findAndConfigurePageControlInView:self.view];
return self.promotionsVCs.count;
}
it works for me
UIPageControl *pageControl = [UIPageControl appearanceWhenContainedIn:[MyViewController class], nil];
pageControl.pageIndicatorTintColor = [UIColor whiteColor];
pageControl.currentPageIndicatorTintColor = [UIColor redColor];
pageControl.backgroundColor = [UIColor blackColor];
This will change the appearance just for "MyViewController". If you want to have different colors in different page indicators on the same view you have to create different subviews and customize them individually.
Here's what I did in Swift 4. I tried similar answers first, in viewDidLoad, but this is what eventually worked. This same snippet was used to answer similar SO questions.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for view in self.view.subviews{
if view is UIPageControl{
(view as! UIPageControl).currentPageIndicatorTintColor = .yellow
}
}
}
Once you have the UIPageControl in this block, you should be able to customize its indicator colours
If you use the "auto generated" page indicator created by UIPageViewController, I think that you can't customize it. The only way you could do that is to add an extra PageControl, either the one provided by Apple or a custom one as #Maschel proposed.
It is possible to customise it through appearance. You can do it in AppDelegate like this.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor whiteColor];
pageControl.currentPageIndicatorTintColor = [UIColor blackColor];
pageControl.backgroundColor = [UIColor lightGrayColor];
return YES;
}
If you want to do it just for a certain view controller, replace the pageControl with this instead.
UIPageControl *pageControl = [UIPageControl appearanceWhenContainedIn:[MyViewController class], nil];
This one working perfectly for custom image
self.pageControl.pageIndicatorTintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"page_indicater"]];
self.pageControl.currentPageIndicatorTintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"page_indicater_selection"]];
You can use SMPageControl: Github. It works just like the UIPageControl but with more customisation possibilities.
You can easily access the UIPageViewController's pageControl by defining a computed property like this:
var pageControl: UIPageControl? {
for subview in view.subviews {
if let pageControl = subview as? UIPageControl {
return pageControl
}
}
return nil
}
And then customize it to suite your needs like this:
override func viewDidLoad() {
super.viewDidLoad()
pageControl?.backgroundColor = .white
pageControl?.pageIndicatorTintColor = .red
pageControl?.currentPageIndicatorTintColor = .blue
}
Obvious caveat: if Apple ever decides to change the UIPageViewController view hierarchy this will stop working.

how to add two view controllers in UIPageViewcontroller

I m using UIPageViewController on iPad where I need to show a firstviewController in the first page and ContentViewController in the next page in landscape.
If I set the NSArray with two viewControllers the app is crashes at [self.pagviewController setViewController:] with the following exception:
The number of provided view controllers (2) doesn't match the number required (1) for the requested spine location (UIPageViewControllerSpineLocationMin)
Below is the code:
#pragma mark - UIPageViewControllerDataSource Methods
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)viewController textContents]];
if(currentIndex == 0)
{
return nil;
}
ContentViewController *contentViewController = [[ContentViewController alloc] init];
contentViewController.textContents = [self.modelArray objectAtIndex:currentIndex - 1];
return contentViewController;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)viewController textContents]];
if(currentIndex == self.modelArray.count-1)
{
return nil;
}
ContentViewController *contentViewController = [[ContentViewController alloc] init];
contentViewController.textContents = [self.modelArray objectAtIndex:currentIndex + 1];
return contentViewController;
}
//#pragma mark - UIPageViewControllerDelegate Methods
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
if(UIInterfaceOrientationIsPortrait(orientation))
{
//Set the array with only 1 view controller
UIViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:currentViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
//Important- Set the doubleSided property to NO.
self.pageViewController.doubleSided = NO;
//Return the spine location
return UIPageViewControllerSpineLocationMin;
}
else
{
NSArray *viewControllers = nil;
ContentViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)currentViewController textContents]];
if(currentIndex == 0 || currentIndex %2 == 0)
{
UIViewController *nextViewController = [self pageViewController:self.pageViewController viewControllerAfterViewController:currentViewController];
viewControllers = [NSArray arrayWithObjects:currentViewController, nextViewController, nil];
}
else
{
UIViewController *previousViewController = [self pageViewController:self.pageViewController viewControllerBeforeViewController:currentViewController];
viewControllers = [NSArray arrayWithObjects:previousViewController, currentViewController, nil];
}
//Now, set the viewControllers property of UIPageViewController
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
return UIPageViewControllerSpineLocationMid;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
//Instantiate the model array
self.modelArray = [[NSMutableArray alloc] init];
self.vcs = [[NSMutableArray alloc]init];
for (int index = 1; index <= 2 ; index++)
{
[self.modelArray addObject:[NSString stringWithFormat:#"Page %d",index]];
}
//Step 1
//Instantiate the UIPageViewController.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
//Step 2:
//Assign the delegate and datasource as self.
self.pageViewController.delegate = self;
self.pageViewController.dataSource = self;
//Step 3:
//Set the initial view controllers.
appDelegate.contentViewController.textContents = [self.modelArray objectAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObjects:appDelegate.firstViewController,appDelegate.contentViewController,nil];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
//Step 4:
//ViewController containment steps
//Add the pageViewController as the childViewController
[self addChildViewController:self.pageViewController];
//Add the view of the pageViewController to the current view
[self.view addSubview:self.pageViewController.view];
//Call didMoveToParentViewController: of the childViewController, the UIPageViewController instance in our case.
[self.pageViewController didMoveToParentViewController:self];
//Step 5:
// set the pageViewController's frame as an inset rect.
CGRect pageViewRect = self.view.bounds;
pageViewRect = CGRectInset(pageViewRect, 40.0, 40.0);
self.pageViewController.view.frame = pageViewRect;
//Step 6:
//Assign the gestureRecognizers property of our pageViewController to our view's gestureRecognizers property.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
}
The problem is you passing an array containing two view controllers to the page view controller while it expects one at a time, change your array to be like this :
NSArray *viewControllers = #[appDelegate.firstViewController];
You will pass one of the views but viewControllerAfterViewController and viewControllerBeforeViewController will handle the rest.
Ah..Finally got solution for this same issue.., it may helps you..
When we set the spine location to UIPageViewControllerSpineLocationMid, the doubleSided property of the pageViewController is automatically set to YES. This means that the content on page front will not partially show through back. But when this property is set to NO, the content on page front will partially show through back, giving the page a translucent kind of effect. So, in the portrait orientation, we have to set the value to NO, otherwise it would result in an exception.
So in your UIPageviewcontroller delegate method, in else part add this doubleSided property as YES when you return spineLocation as UIPageViewControllerSpineLocationMid
self.pageViewController.doubleSided = YES;
return UIPageViewControllerSpineLocationMid;
self.pageViewController.doubleSided = NO;
return UIPageViewControllerSpineLocationMid;
This is the solution for the exception.
In xcode it self you could find this.
Go to the UIPageViewcontroller class there you could see the explanation for this like:
#property (nonatomic, readonly) UIPageViewControllerSpineLocation spineLocation; // If transition style is 'UIPageViewControllerTransitionStylePageCurl', default is 'UIPageViewControllerSpineLocationMin', otherwise 'UIPageViewControllerSpineLocationNone'.
// Whether client content appears on both sides of each page. If 'NO', content on page front will partially show through back.
// If 'UIPageViewControllerSpineLocationMid' is set, 'doubleSided' is set to 'YES'. Setting 'NO' when spine location is mid results in an exception.
#property (nonatomic, getter=isDoubleSided) BOOL doubleSided; // Default is 'NO'.
Instead of implementing a full data source, you can set the PageViewController with one view controller at a time each time the user pushes a next or back button, like
[pageViewController setViewControllers:#[contentViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
This will animate the page transition as you switch.

Pushing a view on storyboard for Page Control

I'm trying to implement a Page Control to show some pages with the following storyboard:
As you can see, I've the main view with a scroll view (ViewController3) and another view (PageViewController) that represents the one that I want to push on my scroll view.
On viewDidLoad of ViewController3 I call the following method:
- (void)loadScrollViewWithPage:(int)page
{
if (page < 0)
return;
if (page >= NUMBER_OF_PAGES)
return;
PageViewController *currentViewController = [viewControllers objectAtIndex:page];
if ((NSNull *)currentViewController == [NSNull null])
{
currentViewController = [[PageViewController alloc] init];
currentViewController.pageNumber = [NSString stringWithFormat:#"%d", page];
[viewControllers replaceObjectAtIndex:page withObject:currentViewController];
}
// add the controller's view to the scroll view
if (currentViewController.view.superview == nil)
{
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
currentViewController.view.frame = frame;
currentViewController.view.backgroundColor = [UIColor yellowColor];
[self.scrollView addSubview:currentViewController.view];
self.scrollView.backgroundColor = [UIColor redColor];
NSDictionary *numberItem = [contentList objectAtIndex:page];
currentViewController.numberImage.image = [UIImage imageNamed:[numberItem valueForKey:IMAGE_KEY]];
currentViewController.numberTitle.text = [numberItem valueForKey:NAME_KEY];
}
}
If I run the project, views with yellow background are displayed with no labels, nor image views.
As you can see, I set this background color programmatically. From my understanding, this means that the new view is correctly added to ViewController3, but it is not linked to the one configured on the storyboard.
Do you have any suggestions on how to solve this issue?
Thanks in advance,
yassa
You have to instantiate PageViewController instance using [UIStoryboard instantiateViewControllerWithIdentifier:(NSString *)identifier].
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIStoryboard_Class/Reference/Reference.html

Trouble with controlling a ScrollView from a Popover

I'm a junior and I have been really struggling to get this to work, would really appreciate some help.
I am trying to build an App where you can scroll through different WebViews by selecting an item from a table in a popover (while the popover remains in place). Unfortunately, I can't get my scrollView to move when I select an item from the popover view.
I have set up a UIScrollView with page control in a main UIViewController. The scrollView is populated with (pageViewController) UIWebViews. The main UIViewController has a nav bar with a button, when the button is clicked it creates a Popover View. When I select an item from the table in the popover view I want my UIScrollView to scroll to a certain position (equates to a selected page), but the scrollView does not move.
The method below takes the value selected from the popover and uses the page number to determine where the scrollView should scroll to, but it doesn't work because at this point my scrollView is Null.
I can supply more code if needed.
main UIViewController.m code:
- (void)setDetailItem:(id)newDetailItem {
if (detailItem != newDetailItem) {
[detailItem release];
detailItem = [newDetailItem retain];
NSString *pgnum = [[NSString alloc] initWithString:[detailItem description]];
int pg;
if(pgnum == #"Page 1"){
pg =1;
}
if(pgnum == #"Page 2"){
pg =2;
}
if(pgnum == #"Page 3"){
pg =3;
}
[pgnum release];
pageControl.currentPage = pg;
[self loadScrollViewWithPage:pg - 1];
[self loadScrollViewWithPage:pg];
[self loadScrollViewWithPage:pg + 1];
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * pg;
frame.origin.y = 0;
[scrollView scrollRectToVisible:frame animated:YES];
pageControlUsed = YES;
}
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
}
}
This is how I triggered the popOverController
The infoButton is on the navbar.
The scrollView is NOT NULL in the infoButton
- (void)infoButton:(id)sender {
NSLog(#"Entering: infoButton");
// [self inspectView:self.view level:#""];
if (self.popoverController == nil) {
PopoverViewController *popoverViewController =
[[PopoverViewController alloc]
initWithNibName:#"PopoverViewController"
bundle:[NSBundle mainBundle]];
popoverViewController.navigationItem.title = #"Navigation";
UINavigationController *navController =
[[UINavigationController alloc]
initWithRootViewController:popoverViewController];
UIPopoverController *popover =
[[UIPopoverController alloc]
initWithContentViewController:navController];
popover.delegate = self;
[popoverViewController release];
[navController release];
self.popoverController = popover;
[popover release];
//NSLog(#"User pressed the info button");
}
[self.popoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; }
UIPopover, being neither the most obvious class to use memory-management wise, nor the most stable, does not require you to release it before you present it. In fact, doing so causes it to throw a fatal exception! Popovers should be released after they are removed from the screen, and/or in -dealloc.

Resources