Error: Page Control jump twice with single page swap - ios

With the following code, the page control has jumped twice instead of once during a single page swap. I need to add the UIPageViewController as subview as below, how can I make the pagecontrol act right? Thank you!
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate{
var pageViewController: UIPageViewController!
let pagesArray = ["Page1ViewController", "Page2ViewController","Page3ViewController"]
let pageControl : UIPageControl = UIPageControl(frame: CGRectMake(100, 600, 200, 20))
func viewControllerAtIndex(index: Int) -> UIViewController? {
let vc = storyboard?.instantiateViewControllerWithIdentifier (pagesArray[index])
return vc
}
func pageViewController(pageViewController:UIPageViewController,
viewControllerBeforeViewController
viewController: UIViewController) -> UIViewController?{
if var index = pagesArray.indexOf(viewController.restorationIdentifier!){
if index > 0 {
index--
self.pageControl.currentPage = index
return viewControllerAtIndex(index)
}
}
return nil
}
func pageViewController(pageViewController:UIPageViewController,
viewControllerAfterViewController
viewController: UIViewController) -> UIViewController?{
if var index = pagesArray.indexOf(viewController.restorationIdentifier!){
if index < pagesArray.count - 1 {
index++
return viewControllerAtIndex(index)
}
}
return nil
}
override func viewDidLoad() {
super.viewDidLoad()
pageControl.numberOfPages = 3
pageControl.currentPage = 0
pageControl.tintColor = UIColor.redColor()
pageControl.pageIndicatorTintColor = UIColor.blackColor()
pageControl.currentPageIndicatorTintColor = UIColor.orangeColor()
if let vc = storyboard?.instantiateViewControllerWithIdentifier("MyPageViewController")
{
self.addChildViewController(vc)
self.view.addSubview(vc.view)
self.view.addSubview(pageControl)
pageViewController = vc as! UIPageViewController
pageViewController.dataSource = self
pageViewController.delegate = self
pageViewController.setViewControllers([viewControllerAtIndex(0)!], direction: .Forward, animated: true, completion: nil)
pageViewController.didMoveToParentViewController(self)
}
}
}

try this
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?
{
let identifier = viewController.restorationIdentifier
self.index = self.identifiers.indexOfObject(identifier!)
if index == identifiers.count - 1 {
return nil
}
//increment the index to get the viewController before the current one
self.index = self.index + 1
return self.viewControllerAtIndex(self.index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
let identifier = viewController.restorationIdentifier
self.index = self.identifiers.indexOfObject(identifier!)
if index == 0 {
return nil
}
//decrement the index to get the viewController before the current one
self.index = self.index - 1
return self.viewControllerAtIndex(self.index)
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return self.identifiers.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return 0
}

Related

Swipe Page View Controller and update page number

I have a UIPageViewController in my program. I have added a UITextView programmatically at the top of UIPageViewController.I want to update the text of UITextView with each swipe to page 1 of n or 2 of n or ….
How should I update the TextView to have the correct image number? Where should I call updateStatusLabelText function?
The reason why I used UITextView is that I could not add a UILabel with constraints through code to the top of UIPageViewController.
First class is as follows:
class MainPageViewController: UIPageViewController {
let dS = MainPageViewControllerDataSource()
var statusText : String = ""
var statusTextView = UITextView()
override func viewDidLoad() {
super.viewDidLoad()
statusTextView = UITextView(frame: view.bounds)
statusTextView.text = statusText
statusTextView.editable = false
statusTextView.textAlignment = .Center
statusTextView.font = UIFont(name: statusTextView.font!.fontName, size: 18)
statusTextView.textColor = UIColor.blackColor()
view.backgroundColor = UIColor.whiteColor()
view.addSubview(statusTextView)
view.sendSubviewToBack(statusTextView)
}
func updateStatusLabelText(arrayKey:Int){
statusTextView.text = "\(arrayKey + 1) of \(imageArray.count) "
}
override func viewWillAppear(animated: Bool) {
dataSource = dS
setViewControllers([dS.viewControllerAtIndex(0) as TutorialViewController], direction: .Forward, animated: true, completion: nil)
}
}
Second class
class MainPageViewControllerDataSource: NSObject, UIPageViewControllerDataSource,UIPageViewControllerDelegate {
var tutorialViewControllerDelegate: TutorialViewControllerDelegate?
var pageIndex = Int()
func viewControllerAtIndex(index: Int) -> TutorialViewController {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("tutorialVC") as! TutorialViewController
vc.myImage = imageArray[index]
vc.pageIndex = index
self.pageIndex = index
return vc
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var index = (viewController as! TutorialViewController).pageIndex
index -= 1
switch index {
case Int.min ... (-1):
return nil
case NSNotFound:
fatalError("NSNotFound. Should crash.")
case imageArray.count..<Int.max:
return nil
default:
return viewControllerAtIndex(index)
}
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var index = (viewController as! TutorialViewController).pageIndex
index += 1
switch index {
case Int.min ... (-1):
return nil
case NSNotFound:
fatalError("NSNotFound. Should crash.")
case imageArray.count ..< Int.max:
return nil
default:
return viewControllerAtIndex(index)
}
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return imageArray.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return pageIndex - 1
}
}
Third class:
class TutorialViewController: UIViewController, UIPageViewControllerDelegate {
#IBOutlet weak var imageToPresent: UIImageView!
var itemIndex: Int = 0
var myImage : MyImage?
var pageIndex = Int()
override func viewDidLoad() {
super.viewDidLoad()
imageToPresent = myImage
}
}

BAD_ACCESS on UIPageViewController

I've got a working UIPageViewController that holds multiple UIViewControllers embedded in an UINavigationController and each UIViewController has a preview of an array of images wich, when opened, instantiate a new UIPageViewController to display those images
when i swipe through the images and then swipe back to the first one my app crashes with "EXC_BAD_ACCESS(code=EXC_I386_GPFLT)" same thing when i use the back button of the UINavigationController
why is that and how can i fix this ?
My PageViewController (the marked line is the last one i got in the debugger before it crashes):
class DetailPageMasterViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource
{
var presentationPageIndex: Int = 0
var itemsArray = [Aktion]()
var pageViewController: UIPageViewController!
#IBOutlet weak var btnEditOutlet: UIBarButtonItem!
#IBAction func btnEditAction(sender: AnyObject)
{
}
override func viewDidLoad()
{
super.viewDidLoad()
self.pageViewController = UIPageViewController.init(transitionStyle: .Scroll,
navigationOrientation: .Horizontal,
options: nil)
self.pageViewController.delegate = self
self.pageViewController.dataSource = self
self.presentationPageIndex = 0
let firstVC = self.viewControllerAtIndex(presentationPageIndex)
let viewControllers = [firstVC]
self.pageViewController.setViewControllers(viewControllers,
direction: .Forward,
animated: false,
completion: nil)
self.addChildViewController(self.pageViewController)
self.view.addSubview(self.pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
self.setupPageControl()
}
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
{
if completed
{
let minionVC = self.pageViewController.viewControllers?.last as! DetailMinionViewController
presentationPageIndex = minionVC.pageIndex
}
}
func viewControllerAtIndex(index: Int) -> DetailMinionViewController
{
let contentVC = self.storyboard?.instantiateViewControllerWithIdentifier("MinionPageViewController") as! DetailMinionViewController
contentVC.aktion = itemsArray[index]
contentVC.pageIndex = index
return contentVC
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
if let viewController = viewController as? DetailMinionViewController
{
var index = viewController.pageIndex
if index == 0 || index == NSNotFound
{
return nil //MARKED LINE
}
index -= 1
return self.viewControllerAtIndex(index)
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?
{
if let viewController = viewController as? DetailMinionViewController
{
var index = viewController.pageIndex
if index == NSNotFound
{
return nil
}
index += 1
if index == NSNotFound || index >= itemsArray.count
{
return nil
}
return self.viewControllerAtIndex(index)
}
return nil
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return itemsArray.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return presentationPageIndex
}
func setupPageControl()
{
UIPageControl.appearance().backgroundColor = UIColor.clearColor()
UIPageControl.appearance().pageIndicatorTintColor = UIColor.whiteColor()
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.redColor()
}
}
So the structure looks like
UINavigationController -> DetailPageMasterViewController -> DetailMinionViewController -> PicturesPageMasterViewController -> PicturesMinionViewController
So i finally figured out what caused my app to crash.
Long story short:
a gestureRecognizer in the PicturesMinionViewController tried to access an already deinitialized ImageView, my pageViewController worked fine
Please check the number of viewController added into the PageController. If possible you can share your code.

UIPageViewController Blank Screen

I am using a UIPageViewController to load multiple UIViewControllers but every time I try scrolling past the last ViewController or even try scrolling the opposite direction on the start of the pageController I get a blank screen as shown below. The blank view is never really fully loaded onto the view but ideally I would like the blank screen to simply have a white colour background hence not obviously visible to the user.
Any help will be greatly appreciated.
import UIKit
class MainPageVC: UIPageViewController
{
var totalPages: [UIViewController] = [UIViewController]()
#IBOutlet weak var rightBarButtonItem: UIBarButtonItem!
override func viewDidLoad()
{
super.viewDidLoad()
let attributes: [String : AnyObject] = [NSFontAttributeName: Constants.defaultFont]
rightBarButtonItem.setTitleTextAttributes(attributes, forState: .Normal)
self.delegate = self
self.dataSource = self
let eyeWearVC = storyboard!.instantiateViewControllerWithIdentifier("eyeWear") as! EyeWearVC
let fitnessVC = storyboard!.instantiateViewControllerWithIdentifier("fitness") as! FitnessVC
let healthVC = storyboard!.instantiateViewControllerWithIdentifier("health") as! HealthVC
let environmentVC = storyboard!.instantiateViewControllerWithIdentifier("environment") as! EnvironmentVC
totalPages.append(eyeWearVC)
totalPages.append(fitnessVC)
totalPages.append(healthVC)
totalPages.append(environmentVC)
setViewControllers([eyeWearVC], direction: .Forward, animated: true, completion: nil)
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
func viewControllerAtIndex(index: Int)-> UIViewController
{
if self.totalPages.count == 0 || index >= self.totalPages.count
{
return UIViewController()
}
return totalPages[index]
}
extension MainPageVC: UIPageViewControllerDelegate
{
}
extension MainPageVC: UIPageViewControllerDataSource
{
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return totalPages.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return 0
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
var currentIndex: Int = totalPages.indexOf(viewController)!
if currentIndex == 0 || currentIndex == NSNotFound
{
return nil
}
currentIndex -= 1
return self.viewControllerAtIndex(currentIndex)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?
{
var currentIndex: Int = totalPages.indexOf(viewController)!
if currentIndex == NSNotFound
{
return nil
}
currentIndex += 1
if currentIndex == totalPages.count
{
return nil
}
return self.viewControllerAtIndex(currentIndex)
}
}
Add
view.backgroundColor = .whiteColor()
in viewDidLoad()

Page View controller content not displaying its widgets

the page view controller is not displaying its content view controller,
please can anyone help to figure the error and help with a solution
thanks
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource {
var pageViewController: UIPageViewController!
var hymnTitles: [String]!
var hymnContents: [String]!
let hymn1 = "this is my story , this is my song"
let hymn2 = "Amazing grace how sweet thou art"
let hymn3 = "God moves in a mysterious way"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.hymnTitles = ["Hymn 1", "Hymn 2", "Hymn 3"]
self.hymnContents = [hymn1, hymn2, hymn3]
self.pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as! UIPageViewController
self.pageViewController.dataSource = self
let startVC = self.viewControllerAtIndex(0) as ContentViewController
let viewControllers = NSArray(object: startVC)
self.pageViewController.setViewControllers(viewControllers as? [UIViewController], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
self.pageViewController.view.frame = CGRectMake(0, 30, self.view.frame.width, self.view.frame.height - 60)
self.addChildViewController(self.pageViewController)
self.view.addSubview(self.pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
}
func viewControllerAtIndex(index: Int) -> ContentViewController
{
if ((self.hymnTitles.count == 0) || (index >= self.hymnTitles.count)) {
return ContentViewController()
}
let vc: ContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController
vc.hymnContent = self.hymnContents[index]
vc.titleText = self.hymnTitles[index]
vc.pageIndex = index
return vc
}
// MARK: - Page View Controller Data Source
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
let vc = viewController as! ContentViewController
var index = vc.pageIndex as Int
if (index == 0 || index == NSNotFound)
{
return nil
}
index--
return self.viewControllerAtIndex(index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let vc = viewController as! ContentViewController
var index = vc.pageIndex as Int
if (index == NSNotFound)
{
return nil
}
index++
if (index == self.hymnTitles.count)
{
return nil
}
return self.viewControllerAtIndex(index)
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return self.hymnTitles.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return 0
}
}
}
the page view controller is not displaying its content view controller,
please can anyone help to figure the error and help with a solution
thanks
You need to add all the required functions of a page view controller.
Try adding the following code:
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
var index = (viewController as! ContentViewController).pageIndex
if (index == 0) || (index == NSNotFound) {
return nil
}
index--
return viewControllerAtIndex(index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController?
{
var index = (viewController as! ContentViewController).pageIndex
if index == NSNotFound {
return nil
}
index++
if (index == self.pageTitles.count) {
return nil
}
return viewControllerAtIndex(index)
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return self.pageTitles.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return 0
}

Hi Swift type does not conform to protocol NilliteralConvertible

//For Navigation Bar Tint and BG Color
var NavBarBGColor = CommonUtilities.RGBColor("#2574A9")
var NavBarTintColor = UIColor.whiteColor()
var pageViewController: UIPageViewController!
var pageTitles: NSArray!
var pageImages: NSArray!
#IBOutlet weak var Open: UIBarButtonItem!
override func viewDidLoad() {
//Navigation Bar Tint and BG Color
self.navigationController?.navigationBar.tintColor = NavBarTintColor
self.navigationController?.navigationBar.barTintColor = NavBarBGColor
super.viewDidLoad()
//Menu Button Click
Open.target = self.revealViewController()
Open.action = Selector("revealToggle:")
//Pan Gesture Recognizer for page navigation
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
//Page View Controller for Men
self.pageTitles = NSArray(objects: "Try","And")
self.pageImages = NSArray(objects: "page1","page2")
self.pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as! UIPageViewController
self.pageViewController.dataSource = self.pageViewController.dataSource
/*var startVC = self.viewControllerIndex(0) as ContentMenuViewController
var viewControllers = NSArray(object: startVC)
self.pageViewController.ViewControllers(viewControllers, direction: .Forward, animated: true, completion: nil)*/
self.pageViewController.view.frame = CGRectMake(0, 30, self.view.frame.width, self.view.frame.size.height - 60)
self.addChildViewController(self.pageViewController)
self.view.addSubview(self.pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func MenuRestartBtn(sender: AnyObject) {
}
func viewControllerAtIndex(index: Int) -> ContentMenuViewController
{
if ((self.pageTitles.count == 0)) || (index >= self.pageTitles.count)
{
return ContentMenuViewController()
}
var vc: ContentMenuViewController = self.storyboard?.instantiateViewControllerWithIdentifier("") as! ContentMenuViewController
vc.imageFile = self.pageImages[index] as! String
vc.titleText = self.pageTitles[index] as! String
vc.pageIndex = index
return vc
}
//Page View Controller Data Source
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var vc = viewController as! ContentMenuViewController
var index = vc.pageIndex as Int
if (index == 0 || index == NSNotFound)
{
return nil
}
index--
return self.viewControllerAtIndex(index)
}
func pageViewController(pageController: UIPageViewController, ViewControllerAfterViewController viewController: UIViewController) -> UIViewController{
var vc = viewController as! ContentMenuViewController
var index = vc.pageIndex as Int
if (index == NSNotFound){
return nil;
}
index ++
if (index == self.pageTitles.count){
return nil
}
return self.viewControllerAtIndex(index)
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return self.pageTitles.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
}
You cannot return nil when function should return UIViewController wich your trying to do in:
func pageViewController(pageController: UIPageViewController, ViewControllerAfterViewController viewController: UIViewController) -> UIViewController
Replace above with:
func pageViewController(pageController: UIPageViewController, ViewControllerAfterViewController viewController: UIViewController) -> UIViewController?

Resources