no page control displayed even after implementing delegate methods - ios

Page view controller not display after adding delegate and datasource. how to implement pageViewController Datasource and delegate
import UIKit
DataSource
class PageViewController: UIPageViewController ,UIPageViewControllerDataSource,UIPageViewControllerDelegate
{
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let vc = storyboard?.instantiateViewController(withIdentifier: "vc") as! ViewController
return vc
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let vc = storyboard?.instantiateViewController(withIdentifier: "vc") as! ViewController
return vc
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return 3
}
override func index(ofAccessibilityElement element: Any) -> Int {
return 0
}
setting a delegate and datasource in ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
dataSource=self
delegate = self
let vc = storyboard?.instantiateViewController(withIdentifier: "vc") as! ViewController
self.setViewControllers([vc], direction: .forward, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Replacing
override func index(ofAccessibilityElement element: Any) -> Int {
return 0
}
with
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
did the work.
I was calling wrong method

Related

iOS swift UIPageViewController with container

I have a strange behavior with UIPageViewController.
Steps :
Open view controller
Tap on camera button
Choose picture
When return back, the included View Controller into the ContainerView take all place in View Controller
Here is my code :
class ContainerPagerViewController: BaseUIViewController {
// The UIPageViewController
var pageContainer: UIPageViewController!
override func viewDidLoad() {
super.viewDidLoad()
// Create the page container
pageContainer = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
// Add it to the view
view.addSubview(pageContainer.view)
}
}
class RPViewController: BaseUIViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
var containerViewController: ContainerPagerViewController?
// Track the current index
var currentIndex: Int?
private var pendingIndex: Int?
private(set) lazy var pages: [UIViewController] = {
return [self.addViewController(identifier: "ViewController1"),
self.addViewController(identifier: "ViewController2"),
self.addViewController(identifier: "ViewController3"),
self.addViewController(identifier: "ViewController4"),
self.addViewController(identifier: "ViewController5"),
self.addViewController(identifier: "ViewController6")]
}()
override func viewDidLoad() {
super.viewDidLoad()
currentIndex = 0
containerViewController?.pageContainer.delegate = self
containerViewController?.pageContainer.dataSource = self
}
private func addViewController(identifier: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil) .
instantiateViewController(withIdentifier: identifier) as! UIViewController
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "containerSegue" {
containerViewController = segue.destination as? ContainerPagerViewController
}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
pendingIndex = pages.index(of: pendingViewControllers.first! as! UIViewController)
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
currentIndex = pendingIndex
}
}
}
}

UIPageController: Turning the page forward then backward quickly only updates the first page

I have the class SliderPgaeViewController: UIPageViewController with scroll transition style as follows:
class SliderPgaeViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource, PlayerUpdatePageControllerDelegate {
var lastPendingIndex: Int = 0
var sliderPageDelegate: SliderPageDelegate? = nil
let playerManager = PlayerManager.getInstance()
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
setViewControllers([createViewController(index: playerManager.getCurrentIndex())!], direction: .forward, animated: true, completion: nil)
lastPendingIndex = playerManager.getCurrentIndex()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return playerManager.getSongsCount()
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if let vc = viewController as? PlayerImageViewController {
if (vc.index == 0){
return nil
}
return createViewController(index: vc.index! - 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if let vc = viewController as? PlayerImageViewController {
if (vc.index == playerManager.getSongsCount() - 1){
return nil
}
return createViewController(index: vc.index! + 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]){
if let vc = pendingViewControllers[0] as? PlayerImageViewController {
self.lastPendingIndex = vc.index!
}
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool,previousViewControllers: [UIViewController],transitionCompleted completed: Bool) {
print("before completion : \(self.lastPendingIndex)")
if(completed){
print("completed : \(self.lastPendingIndex)")
if (viewControllers?.first as? PlayerImageViewController) != nil {
sliderPageDelegate?.updateSong(index: self.lastPendingIndex, dir: 0)
}
}
}
private func createViewController(index i: Int) -> UIViewController?{
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PlayerImageController") as! PlayerImageViewController
vc.index = i
vc.image = playerManager.getSong(index: i).image
return vc
}
...
I am using this page controller to display the thumbnail of a song in a music player. And when the user turn a page the player changes the song playing by calling sliderPageDelegate?.updateSong(index: self.lastPendingIndex, dir: 0) in pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool,previousViewControllers: [UIViewController],transitionCompleted completed: Bool)
When I'm turning the page forward and then immediately backward, the page is turning correctly (first forward then backward); however, sliderPageDelegate?.updateSong(index: self.lastPendingIndex, dir: 0) is only being called in the forward direction.
So, if we have list of songs (A, B, C, ...) and we are currently at song A. When the user swipes forward, the thumbnail changes to B's thumbnail and the player updates the song to B. However, if the forward swipe was followed by a backward swipe quickly, then the thumbnail changes to A but the song remains B
Update:
if A has index = 0 and B has index = 1, moving A->B->A quickly will print the following:
before completion : 1
before completion : 1
completed : 1
I have added PageControllerDelegate in your code and introduce two new methods. Then implement these delegates in your UIPageViewController class and then in PlayerImageViewController class invoke both methods in viewWillAppear and viewWillDisappear. Now remove you didFinishAnimation method and write that code in viewControllerIsBeingDisplay.
For deeper knowledge review this code.
class PlayerImageViewController: UIViewController {
var index: Int?
var image: UIImage?
weak var delegate: PageControllerDelegate?
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let del = self.delegate {
del.viewControllerIsBeingHide(self)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let del = self.delegate {
del.viewControllerIsBeingDisplay(self)
}
}
}
protocol SliderPageDelegate {
func updateSong(index: Int, dir: Int)
}
protocol PageControllerDelegate {
func viewControllerIsBeingHide(_ viewController: PlayerImageViewController)
func viewControllerIsBeingDisplay(_ viewController: PlayerImageViewController)
}
class SliderPgaeViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource, PageControllerDelegate {
var lastPendingIndex: Int = 0
var sliderPageDelegate: SliderPageDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
setViewControllers([createViewController(index: playerManager.getCurrentIndex())!], direction: .forward, animated: true, completion: nil)
lastPendingIndex = playerManager.getCurrentIndex()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return playerManager.getSongsCount()
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if let vc = viewController as? PlayerImageViewController {
if (vc.index == 0){
return nil
}
return createViewController(index: vc.index! - 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if let vc = viewController as? PlayerImageViewController {
if (vc.index == playerManager.getSongsCount() - 1){
return nil
}
return createViewController(index: vc.index! + 1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]){
if let vc = pendingViewControllers[0] as? PlayerImageViewController {
self.lastPendingIndex = vc.index!
}
}
private func createViewController(index i: Int) -> UIViewController?{
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PlayerImageController") as! PlayerImageViewController
vc.index = i
vc.delegate = self
// vc.image = playerManager.getSong(index: i).image //Commented becoz i do not have this file
return vc
}
var previousVCIndex = 0
func viewControllerIsBeingHide(_ viewController: PlayerImageViewController) {
previousVCIndex = viewController.index!
}
func viewControllerIsBeingDisplay(_ viewController: PlayerImageViewController) {
if let del = sliderPageDelegate {
del.updateSong(index: previousVCIndex, dir: 0)
}
}
}

UIPageViewController in Container not displaying other View Controllers

Ok, could someone please help with my Swift code that I'm trying to fix.
I have read other question on here similar to mine but to no avail unfortunately.
The problem is that I have a UIPageViewController in a Container but when I test it on the iPhone, it won't display the two views I have set (there is actually 9 views but only put 2 in the code for now so I can get it working).
Here is my code:
import UIKit
class pvController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var pages = [UIViewController]()
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
self.dataSource = self
let page1: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "vController1")
let page2: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "vController2")
pages.append(page1)
pages.append(page2)
setViewControllers([page1], direction: UIPageViewControllerNavigationDirection.forward, animated: false)
// Do any additional setup after loading the view, typically from a nib.
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.index(of: viewController)
let previousIndex = abs((currentIndex! - 1) % pages.count)
return pages[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.index(of: viewController)
let nextIndex = abs((currentIndex! + 1) % pages.count)
return pages[nextIndex]
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return pages.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I did initially try doing it with SwipeGestureRecogniser although I couldn't get it to work/figure it out.
Also I am fairly new to this so it may be something simple that I just can't figure out.
Thanks in advance

transition page with uipageviewcontroller

I have a view container containing a UIPageViewController. to him they are associated with 2 viewController of UIImageView. It works almost everything. I can not change the animations to scroll through images. the animation is always that of the page curl while I would like a simple scroll. how to do?
class MyPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var pages = [UIViewController]()
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
self.dataSource = self
let page1: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "page1")
let page2: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "page2")
pages.append(page1)
pages.append(page2)
setViewControllers([page1], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.index(of: viewController)!
let previousIndex = abs((currentIndex - 1) % pages.count)
return pages[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.index(of: viewController)!
let nextIndex = abs((currentIndex + 1) % pages.count)
return pages[nextIndex]
}
private func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return pages.count
}
private func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
}
How are you initiating the UIPageViewController?
From code, you can specify a transitionStyle in the constructor, as seen here
From storyboard, you can specify the same transitionStyle in the storyboard itself, as shown in this SO answer

UIPageControl to show current page

I made a PageViewController to switch between different View Controllers, and i'd like to show which page we see. I added a pageControl, and gave it the following code.
pageControl.currentPageIndicatorTintColor = UIColor.blueColor()
pageControl.pageIndicatorTintColor = UIColor.lightGrayColor()
pageControl.numberOfPages = pages.count
The complete code:
import UIKit
class ViewControllerSportinfrastructuur: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
#IBOutlet weak var pageControl: UIPageControl!
var pageViewController: UIPageViewController!
let pages = ["PageOneViewController", "PageTwoViewController"]
//MARK: - page view controller data source
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
if let index = pages.indexOf(viewController.restorationIdentifier!) {
if index > 0 {
return viewControllerAtIndex(index - 1)
}
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
if let index = pages.indexOf(viewController.restorationIdentifier!) {
if index < pages.count - 1 {
return viewControllerAtIndex(index + 1)
}
}
return nil
}
func viewControllerAtIndex(index: Int) -> UIViewController? {
let vc = storyboard?.instantiateViewControllerWithIdentifier(pages[index])
return vc
}
override func viewDidLoad() {
super.viewDidLoad()
if let vc = storyboard?.instantiateViewControllerWithIdentifier("MyPageViewController") {
self.addChildViewController(vc)
self.view.addSubview(vc.view)
pageViewController = vc as! UIPageViewController
pageViewController.dataSource = self
pageViewController.delegate = self
pageViewController.setViewControllers([viewControllerAtIndex(0)!], direction: .Forward, animated: true, completion: nil)
pageViewController.didMoveToParentViewController(self)
pageControl.currentPageIndicatorTintColor = UIColor.blueColor()
pageControl.pageIndicatorTintColor = UIColor.lightGrayColor()
pageControl.numberOfPages = pages.count
}
}
Does anyone know what code i should use to set up the current page? Thanks in advance!
EDIT: found the answer already!
I added pageControl.currentPage = index in following functions:
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
if let index = pages.indexOf(viewController.restorationIdentifier!) {
pageControl.currentPage = index
if index > 0 {
return viewControllerAtIndex(index - 1)
}
}
return nil
}
And did the same for the viewControllerAfterViewController func!
The UIPageViewController provides a default UIPageControl - I would recommend to make use of it if you don't have particular custom requirements.
In order to show it you need to implement the following two optional methods in your UIPageViewControllerDataSource:
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return n //number of view controllers
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return i //index of the visible view controller
}
Set pageViewController.delegate = self, implement protocol UIPageViewControllerDelegate
and use on of these methods to set self.pageControl.currentPage = ...
optional func pageViewController(_ pageViewController: UIPageViewController,
willTransitionToViewControllers pendingViewControllers: [UIViewController])
optional func pageViewController(_ pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers previousViewControllers: [UIViewController],
transitionCompleted completed: Bool)

Resources