Loading View Controllers in UIPageViewController - ios

I'm using a UIPageViewController to scroll through 3 view controllers. The goal is to be able to swipe left and right to navigate them, which I'm able to do with the following code. The issue is that on opening the app for the first time, the navigation bars load in the wrong place and need a full second to conform to constraints. The nav bars load higher than they should be. I'm wondering why there's such a delay in them loading.
class ViewController: UIViewController, UIPageViewControllerDataSource {
var myViewControllers = Array(count: 3, repeatedValue:UIViewController())
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let pvc = segue.destinationViewController as! UIPageViewController
pvc.dataSource = self
let storyboard = UIStoryboard(name: "Main", bundle: nil);
var vc0 = storyboard.instantiateViewControllerWithIdentifier("ViewController1") as! UIViewController
var vc1 = storyboard.instantiateViewControllerWithIdentifier("ViewController2") as! UIViewController
var vc2 = storyboard.instantiateViewControllerWithIdentifier("ViewController3") as! UIViewController
self.myViewControllers = \[vc0, vc1, vc2\]
pvc.setViewControllers(\[myViewControllers\[1\]\], direction:.Forward, animated:false, completion:nil)
println("Loaded")
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var currentIndex = find(self.myViewControllers, viewController)!+1
if currentIndex >= self.myViewControllers.count {
return nil
}
return self.myViewControllers\[currentIndex\]
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var currentIndex = find(self.myViewControllers, viewController)!-1
if currentIndex < 0 {
return nil
}
return self.myViewControllers\[currentIndex\]
}

Related

When I pass data from TableView to child PageViewController, it can go to next child

I have an UIViewController with a UITableView. Then I create a PageViewController with two viewcontroller. Pageview doesn't work if I pass data to child. If I change
setViewControllers([subjective], direction: .Forward, animated: true, completion: nil)
to
setViewControllers([firstVC], direction: .Forward, animated: true, completion: nil)
Pageview work but data don't pass. I don't have any idea about it. Help me please. Thanks
Code Work:
pageview controller class:
import UIKit
class PageVC : UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
var lblhoten = String()
var lblngaysinh = String()
var lblsodt = String()
lazy var VCArr: [UIViewController] = {
return [self.VCInstance("ThongTinBNPage2"),
self.VCInstance("ThongTinBNPage3")]
}()
private func VCInstance(name: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier(name)
}
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
if let firstVC = VCArr.first {
let subjective = self.storyboard?.instantiateViewControllerWithIdentifier("ThongTinBNPage2") as! VCSubjective
subjective.lblhoten = lblhoten
subjective.lblngaysinh = lblngaysinh
subjective.lblsodt = lblsodt
setViewControllers([subjective], direction: .Forward, animated: true, completion: nil)
}
}
public func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
guard let viewcontrollerindex = VCArr.indexOf(viewController) else {
return nil
}
let previousindex = viewcontrollerindex - 1
guard previousindex >= 0 else {
return VCArr.last
}
guard VCArr.count > previousindex else {
return nil
}
return VCArr[previousindex]
}
public func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
guard let viewcontrollerindex = VCArr.indexOf(viewController) else {
return nil
}
let nextindex = viewcontrollerindex + 1
guard nextindex < VCArr.count else {
return VCArr.first
}
guard VCArr.count > nextindex else {
return nil
}
return VCArr[nextindex]
}
public func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return VCArr.count
}
// The selected item reflected in the page indicator.
public func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
guard let firstviewcontroller = viewControllers?.first,
let firstviewcontrollerindex = VCArr.indexOf(firstviewcontroller) else {
return 0
}
return firstviewcontrollerindex
}
}
VCSubjective:
import UIKit
class VCSubjective: UIViewController {
#IBOutlet var hoten: UILabel!
#IBOutlet var ngaysinh: UILabel!
#IBOutlet var sodt: UILabel!
var lblhoten = String()
var lblngaysinh = String()
var lblsodt = String()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
hoten.text = lblhoten
ngaysinh.text = lblngaysinh
sodt.text = lblsodt
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The problem here is that you are referencing two completely different objects.
In viewDidLoad you create ThongTinBNPage2 viewController and then add it to the viewControllers property of the pageViewController. However, the objects stored in VCArr are two totally different viewControllers.
Let's think about it this way:
When viewDidLoad is called you create viewController object #1
Then you assign the viewController object #1 to the viewControllers object of the pageViewController making the value of viewControllers = [object #1]
In pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? and pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? you reference the VCArr object. On the first call to VCArr, it lazily creates two completely different view controller objects [object #2, object #3]
To fix this code you need to do the following:
if let firstVC = VCArr.first {
let subjective = firstVC // DO NOT create different VC here
subjective.lblhoten = lblhoten
subjective.lblngaysinh = lblngaysinh
subjective.lblsodt = lblsodt
setViewControllers([subjective], direction: .Forward, animated: true, completion: nil)
}

UITableView in UIPageViewController in NavigationController with Page Control

I have the following set up:
UINavigationController -> UIPageViewController-> UITableViewController/UIViewController/UIViewController
my UIPageViewController looks like this:
import UIKit
class DailyRoutinePageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var pages = [UIViewController]()
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false;
self.delegate = self
self.dataSource = self
self.navigationItem.title = getActiveUserName()
let page1: UIViewController! = storyboard?.instantiateViewControllerWithIdentifier("dailyRoutinePage1")
let page2: UIViewController! = storyboard?.instantiateViewControllerWithIdentifier("dailyRoutinePage2")
let page3: UIViewController! = storyboard?.instantiateViewControllerWithIdentifier("dailyRoutinePage3")
pages.append(page1)
pages.append(page2)
pages.append(page3)
setViewControllers([page1], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
#IBAction func buttonKontakte(sender: AnyObject) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("careTaker")
self.presentViewController(vc, animated: true, completion: nil)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.indexOf(viewController)!
let previousIndex = abs((currentIndex - 1) % pages.count)
return pages[previousIndex]
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.indexOf(viewController)!
let nextIndex = abs((currentIndex + 1) % pages.count)
return pages[nextIndex]
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return pages.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
}
this works fine. I can scroll through all pages. Now I want to add a Page Control. I can add a Page Control to the UIPageView's. But how can I add one to the UITableViewController? And when I scroll through the pages the Page Control scroll with the pages. How can I make it stand still?
An other problem: The PageViewController doesn't respect the navigation title bar. So there is content behind the Naviagtion bar at the top. How can I fix this?

pageController with multiple viewControllers

I'm trying to add a pagecontroller with multiple viewControllers. I've started by creating a contentView in interfacebuilder and embedded a pageController in it. Then i've added below code, but it does not seem to show anything?
let initialViewController = self.viewControllerAtIndex(0)
self.pageViewController?.setViewControllers([initialViewController], direction: .Forward, animated: false, completion: nil)
PAgeViewController Extension
var viewControllerIdentifiers = ["BottomNoLogo", "TopNoLogo"]
extension CameraViewController: UIPageViewControllerDataSource {
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let currentText = viewController.restorationIdentifier
var currentIndex = viewControllerIdentifiers.indexOf(currentText!)
if currentIndex == viewControllerIdentifiers.count - 1 {
return viewControllerAtIndex(0)
} else {
return viewControllerAtIndex(++currentIndex!)
}
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let currentText = viewController.restorationIdentifier
var currentIndex = viewControllerIdentifiers.indexOf(currentText!)
if currentIndex == 0 {
return viewControllerAtIndex(viewControllerIdentifiers.count - 1)
} else {
return viewControllerAtIndex(--currentIndex!)
}
}
func viewControllerAtIndex(index: Int) -> UIViewController {
let contentViewController = storyboard?.instantiateViewControllerWithIdentifier(viewControllerIdentifiers[index])
return contentViewController!
}
}
The page view controller really just provides the dots: you've still got to add the controllers' views as subviews of the parent view and manage the scrolling. There are lots of examples out there. See http://www.appcoda.com/uipageviewcontroller-tutorial-intro/, for example.

Disable swipe function in UIViewController

I have a UIPageViewController with two ViewControllers in it, one of them got a NavigationController connected so i can push to another ViewController using the Push-Segue embedded in a button. The ViewController that is being pushed have the UIPageViewController datasource enabled so i can swipe from the pushed ViewController back to the first ViewController.
I want to be able to disable the swip function in the pushed ViewController so i must press on the back button to return, not swipe.
I think that my UIPageViewController is not setting the correct view in the function before and after.
Code for UIPageViewController
class upAndDownViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var pages = [UIViewController]()
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
self.dataSource = self
let page2: UIViewController! = storyboard?.instantiateViewControllerWithIdentifier("page2")
let topPage: UIViewController! = storyboard?.instantiateViewControllerWithIdentifier("topPage")
pages.append(page2)
pages.append(topPage)
setViewControllers([page2], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.indexOf(viewController)!
let nextIndex = abs((currentIndex + 1) % pages.count)
if (nextIndex < 1)
{
return nil
}
return pages[nextIndex]
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let currentIndex = pages.indexOf(viewController)!
let previousIndex = abs((currentIndex - 1) % pages.count)
if (previousIndex > 0)
{
return nil
}
return pages[previousIndex]
}

Overriding Swiping Actions on a UITableView over UIPageController VC segues

In swift, i'm currently working on segueing my VC's using a UIPageViewController, where when you swipe left or right it changes the VC. In one of my View Controllers, a table view exists, where if you swipe on the row there are options. My problem is, when I swipe on the row of the table, it changes to my View Controller. I want to override this so that it shows row actions before VC swiping. My code below is the first VC. PS: If you need my Code for my tableviews please comment for it! Thanks
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var myViewControllers = Array(count: 4, repeatedValue:UIViewController())
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let pvc = segue.destinationViewController as UIPageViewController
pvc.dataSource = self
let storyboard = UIStoryboard(name: "Main", bundle: nil);
var vc0 = storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as UIViewController
var vc1 = storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as UIViewController
var vc2 = storyboard.instantiateViewControllerWithIdentifier("ThirdViewController") as UIViewController
var vc3 = storyboard.instantiateViewControllerWithIdentifier("FourthViewController") as UIViewController
self.myViewControllers = [vc0, vc1, vc2, vc3]
pvc.setViewControllers([myViewControllers[1]], direction:.Forward, animated:false, completion:nil)
println("Loaded")
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var currentIndex = find(self.myViewControllers, viewController)!+1
if currentIndex >= self.myViewControllers.count {
return nil
}
return self.myViewControllers[currentIndex]
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
var currentIndex = find(self.myViewControllers, viewController)!-1
if currentIndex < 0 {
return nil
}
return self.myViewControllers[currentIndex]
}
}
Did the tableView takes all the space in your view? let's try with
override func scrollViewDidScroll(scrollView: UIScrollView) {
}

Resources