I've used a tutorial on AppCoda for adding a sort of tutorial style UIPageViewController - it works amazingly - it's just that I can't remove it on a button click.
Here's my PageViewController:
#import "startupViewController.h"
#import "SKSlideViewController.h"
#import "APPChildViewController.h"
#interface startupViewController ()
#end
#implementation startupViewController
#synthesize outletWallpaper;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self mymethod];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)mymethod {
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
[[self.pageController view] setFrame:[[self view] bounds]];
APPChildViewController *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];
}
- (APPChildViewController *)viewControllerAtIndex:(NSUInteger)index {
APPChildViewController *childViewController = [[APPChildViewController alloc] initWithNibName:#"APPChildViewController" bundle:nil];
childViewController.index = index;
return childViewController;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [(APPChildViewController *)viewController index];
if (index == 0) {
return nil;
}
// Decrease the index by 1 to return
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [(APPChildViewController *)viewController index];
index++;
if (index == 3) {
return nil;
}
return [self viewControllerAtIndex:index];
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
// The number of items reflected in the page indicator.
return 3;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
// The selected item reflected in the page indicator.
return 0;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
NSLog(#"Switching View Controllers...");
SKSlideViewController *slideController=(SKSlideViewController *)[segue destinationViewController];
[slideController setStoryBoardIDForMainController:#"MainVC" leftController:#"LeftVC" rightController:#"RightVC"];
[slideController reloadControllers];
}
#end
This code sends me to another file which from there, I need to remove the whole thing.
I think I did the same tutorial on appcoda, and had the same question!
A solution that has worked for me I stumbled across accidentally on another question:
// Replace deleteVC with your UIPageViewController
[deleteVC willMoveToParentViewController:nil];
[deleteVC.view removeFromSuperview];
[deleteVC removeFromParentViewController];
var movingIndex = 0
var forwardDirection = false
if selectedIndex == images.count{ //ur pages dataSource You may not need this
movingIndex = selectedIndex - 1
forwardDirection = false
} else {
movingIndex = selectedIndex
forwardDirection = true
}
controllers.remove(at: selectedIndex)
capturedInspectionPhotoView.imagePageController?.dataSource = self
capturedInspectionPhotoView.imagePageController?.setViewControllers([controllers[movingIndex]],
direction: forwardDirection ? .forward : .reverse, animated: true)
Related
I can't seem to get a UIPageViewController working. With the code below, the PageViewController calls all of its data source methods and even shows the corresponding dots, but the actual content views are not displayed (even though I checked in debug that the view controllers are instantiated correctly). Does anyone have a clue what I'm doing wrong?
EDIT: the view controller is not nil, but all its properties are. Apparently there is something going wrong with the instantiation.
//content view controller containing a text label
#import "TutorialPhoneContentViewController.h"
#interface TutorialRootViewController ()
#end
#implementation TutorialRootViewController {
NSInteger numberOfViewControllers;
}
- (void)viewDidLoad {
[super viewDidLoad];
numberOfViewControllers = 3;
[self setUpViewControllers];
}
- (void)setUpViewControllers {
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.dataSource = self;
TutorialPhoneContentViewController *ctrl = [self viewControllerAtIndex:0];
[self.pageViewController setViewControllers:#[ctrl] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self.pageViewController willMoveToParentViewController:self];
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
}
- (TutorialPhoneContentViewController *)viewControllerAtIndex:(NSInteger)index {
//this returns the correct view controller, checked via debug
TutorialPhoneContentViewController *ctrl = [self.storyboard instantiateViewControllerWithIdentifier:#"tutorialContentViewController"];
ctrl.index = index;
ctrl.text = [NSString stringWithFormat:#"View Controller #%ld", index];
return ctrl;
}
#pragma mark - Page View Controller
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSInteger index = [(TutorialPhoneContentViewController *)viewController index];
if (index == 0) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSInteger index = [(TutorialPhoneContentViewController *)viewController index];
if (index == numberOfViewControllers-1) {
return nil;
}
index++;
return [self viewControllerAtIndex:index];
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
return numberOfViewControllers;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
return 0;
}
I have a UIViewController which has a UIPageViewController property. The problem I am running into is when a viewcontroller is dragging (uitableview/uitableviewcell), the pageviewcontroller swipe takes over and changes the page when scrolling in its childrencontroller view.
I tried adding a gesture and checking if the touch is a UITableViewCell to prevent gesture touch but its not working.
I am trying to achieve similar feel that twitter or snapchat app have when you swipe left to right a new viewcontroller view is shown.
#import "ContainerViewController.h"
#interface ContainerViewController () <UIPageViewControllerDataSource, UIPageViewControllerDelegate, UIGestureRecognizerDelegate>
#property (nonatomic, strong) UIPageViewController *pageViewController;
#end
#implementation ContainerViewController
- (id)initWithViewControllers:(NSArray *)viewControllers
{
self = [super init];
if (self) {
self.viewControllers = viewControllers;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view addSubview:self.pageViewController.view];
}
#pragma mark - Accessors
- (UIPageViewController *)pageViewController
{
if (_pageViewController) {
return _pageViewController;
}
_pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.0f] forKey:UIPageViewControllerOptionInterPageSpacingKey]];
_pageViewController.dataSource = self;
_pageViewController.delegate = self;
for (UIView *view in _pageViewController.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
UIPanGestureRecognizer *g = [[UIPanGestureRecognizer alloc] initWithTarget:self action:nil];
g.delegate = self;
UIScrollView *scrollView = (UIScrollView *)view;
[scrollView addGestureRecognizer:g];
}
}
[_pageViewController setViewControllers:#[self.viewControllers[1]]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
return _pageViewController;
}
#pragma mark - UIPageViewControllerDataSource
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = [self.viewControllers indexOfObject:viewController];
if (index == 0) {
return nil;
}
return self.viewControllers[index - 1];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = [self.viewControllers indexOfObject:viewController];
if (index >= self.viewControllers.count - 1) {
return nil;
}
return self.viewControllers[index + 1];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
// UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
NSLog(#"PREVENT SCROLLL");
return NO;
}
return YES;
}
#end
I am new to iOS development, and I am having some issues showing images in a simple page view controller photo gallery.
The problem I am having is that the images in the child view won't be displayed. The only thing showing is a blank page.
Here is the view controller file holding page view controller:
#import "RTPGalleryViewController.h"
#import "RTPSinglePhotoViewController.h"
#import "JMImageCache.h"
#interface RTPGalleryViewController ()
#end
#implementation RTPGalleryViewController
#synthesize photosArray, pageViewController, pagesArray;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
pagesArray = [[NSMutableArray alloc] init];
[self generatePhotoViews];
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.dataSource = self;
[[self.pageViewController view] setFrame:[[self view] bounds]];
RTPSinglePhotoViewController *initialViewController = [pagesArray objectAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
[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:self.pageViewController];
[[self view] addSubview:[self.pageViewController view]];
[self.pageViewController didMoveToParentViewController:self];
// Do any additional setup after loading the view.
}
-(void) initWithPhotoArray:(NSMutableArray *) photos{
self.photosArray = photos;
}
-(void) generatePhotoViews{
for (int i=0; i< [photosArray count]; i++) {
RTPSinglePhotoViewController *view = [[RTPSinglePhotoViewController alloc] init] ;
view.imageUrl = [photosArray objectAtIndex:i];
view.pageIndex = i;
[pagesArray addObject:view];
}
}
- (RTPSinglePhotoViewController *)viewControllerAtIndex:(NSUInteger)index
{
NSLog(#"PHOTO ARRAY COUNT IS: %lu", (unsigned long)[photosArray count]);
if ([self.pagesArray count] == 0) {
return nil;
}
return [pagesArray objectAtIndex:index];
;
}
#pragma mark - Page View Controller Data Source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = ((RTPSinglePhotoViewController*) viewController).pageIndex;
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
NSLog(#"THE INDEX NOW IS %lu",(unsigned long)index);
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = ((RTPSinglePhotoViewController*) viewController).pageIndex;
if (index == ([pagesArray count]-1) || index == NSNotFound) {
return nil;
}
NSLog(#"THE INDEX NOW IS %lu",(unsigned long)index);
index++;
return [self viewControllerAtIndex:index];
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return [self.photosArray count];
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
#end
RTPSinglePhotoViewController is the content view controller holding images here is the code:
#import "RTPSinglePhotoViewController.h"
#import "JMImageCache.h"
#interface RTPSinglePhotoViewController ()
#end
#implementation RTPSinglePhotoViewController
#synthesize imageView,imageUrl;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString * path = imageUrl;
NSURL * url = [NSURL URLWithString:path];
// [cell.thumbnailImageView setImageWithURL:url key:nil placeholder:nil completionBlock:nil failureBlock:nil];
[[JMImageCache sharedCache] imageForURL:url completionBlock:^(UIImage *downloadedImage) {
imageView.image = downloadedImage;
} failureBlock:nil];
// Do any additional setup after loading the view.
}
#end
Now, according to the log, the image is being downloaded/cached properly, it is just not showing up. Seeing a blank page instead of photo. What am I doing wrong?
Any suggestions would be appreciated!
I suppose you are not using storyboard.
The way you are allocating view controllers is:
RTPSinglePhotoViewController *view = [[RTPSinglePhotoViewController alloc] init] ;
Where it should be:
RTPSinglePhotoViewController *view = [[RTPSinglePhotoViewController alloc] initWithNibName:#"The name of the xib associated with this controller" bundle: [NSBundle mainBundle]];
The problem is that you are not associating any view to your view controller, therefore nothing is displayed
EDIT: Since you're using storyboards the right way to instantiate the view controller is:
RTPSinglePhotoViewController *view = (RTPSinglePhotoViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"your_controllers_storyboard_id"];
I have a view controller implementing UIPageViewControllerDataSource delegate, and it contains a UIPageViewController.
My issue is that, after 3 hours of tutorials and reading, I still don't understand why the UIPageController reacts to swipe by moving it's content, but it doesn't change the page if the scroll is enough. It's always stuck on the first page.
So this is my .h file
#import <UIKit/UIKit.h>
#interface BreathePageViewController : UIViewController <UIPageViewControllerDataSource>
#property (strong, nonatomic) UIPageViewController *pageController;
#end
And this is my .m file
#import "BreathePageViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h.h"
#interface BreathePageViewController () {
NSArray *pageViewControllerScreens;
FirstViewController *firstViewController;
SecondViewController *secondViewController;
int pageIndex;
}
#end
#implementation BreathePageViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
pageIndex = 0;
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
[[self.pageController view] setFrame:[[self view] bounds]];
[self.pageController setViewControllers:#[firstViewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
[self.view addSubview:self.pageController.view];
[self addChildViewController:self.pageController];
[[self view] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
if (pageIndex == 0) {
return nil;
}
pageIndex--;
return [self viewControllerAtIndex:pageIndex];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
if (pageIndex == 2) {
return nil;
}
pageIndex++;
return [self viewControllerAtIndex:pageIndex];
}
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index {
UIViewController *vc;
if (pageIndex == 0 ) {
vc = [[FirstViewController alloc] init];
}
else if (pageIndex == 1) {
vc = [[SecondViewController alloc] init];
}
return vc;
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
return 2;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
return 0;
}
#end
Now the strange stuff is that the pageViewController:viewControllerAfterViewController is never called.
Can someone help me out?
Thank you
After a night of sleep, I am going to to reply my own question.
I don't know why (any comment appreciated), but the problem was not on that view controller, but it was in the one I was creating it in.
In the parent view controller I was building the UIPageViewController like that:
BreathePageViewController *pageController = [[BreathePageViewController alloc] init];
[pageController.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:pageController.view];
And now I tried to move the declaration of pageViewController as an iVar. And it works.
Hope to help someone else
I'm learning iOS programming from a book, and I've coded an app to make a page turn to another page, similar to iBooks. But when I run it in the simulator, when I swipe to the left or right the page doesn't turn or transition at all. I don't know why.
My code that I believe is relevant is below. I've also attached the whole project in case I've missed anything. Basically there's a UIWebview that is the content for the UIViewController. It gets populated from the model located in the class that acts as the data source for the PageView. Depending on which view controller you go to the appropriate (protocol) method then sets the content in the webview according to the index of the view controller you're going to.
But, it won't work, as said:
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [self indexOfViewController:(ContentViewController *)viewController];
if (index == 0 || index == NSNotFound) {
return nil;
}
else {
index--;
return [self viewControllerAtIndex:index];
}
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [self indexOfViewController:(ContentViewController *)viewController];
if (index == NSNotFound) {
return nil;
}
else {
index--;
return [self viewControllerAtIndex:index];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[self createContentPages];
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:UIPageViewControllerSpineLocationMin]
forKey:UIPageViewControllerOptionSpineLocationKey];
_pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options: options];
_pageController.dataSource = self;
[[_pageController view] setFrame:[[self view] bounds]];
ContentViewController *initialViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
[_pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
[self addChildViewController:_pageController];
[[self view] addSubview:[_pageController view]];
[_pageController didMoveToParentViewController:self];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)createContentPages {
NSMutableArray *pageStrings = [[NSMutableArray alloc] init];
for (int i = 1; i <= 10; i++) {
NSString *contentString = [[NSString alloc] initWithFormat:#"<html><head></head><body><h1>Chapter %d</h1><p>This is the page %d of content displayed using UIPageViewController in iOS 6.</p></body></html>", i, i];
[pageStrings addObject:contentString];
}
self.pageContent = [[NSArray alloc] initWithArray:pageStrings];
}
// Return the data view controller for the given index
- (ContentViewController *)viewControllerAtIndex:(NSUInteger)index {
if (([self.pageContent count] == 0) || index >= [self.pageContent count]) {
return nil;
}
else {
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle mainBundle]];
ContentViewController *dataViewController = [storyBoard instantiateViewControllerWithIdentifier:#"contentView"];
dataViewController.dataObject = self.pageContent[index];
return dataViewController;
}
}
- (NSUInteger)indexOfViewController:(ContentViewController *)viewController {
return [self.pageContent indexOfObject:viewController.dataObject];
}
Whole project: http://cl.ly/1B0l3Z1H1616
In the
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
method, you have
index--
Try changing it to
index++