In the YouTube app, I'm able to continue watching videos via a mini-player in the very bottom right-hand corner (see video below entitled "The Chainsmokers") that's layered atop all other view controllers as I navigate the app. No matter which page I'm on, I can watch the video in the mini player.
If you drag up from the mini player, the video's entire view controller will appear. But it's always atop other pages. I'm trying to understand how to copy this method using Swift so I can watch the video from any page.
The way my app is structured is through a UIPageViewController. I'm embedding three unique navigation controllers (for swipe nav purposes (see code below)). I want to understand how to utilize the mini-player. In YouTube, is that like a mini modal VC? How is it structurally laid out, and if you know, how can I incorporate that into my current layout?
class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
private var pages: [UINavigationController]!
private var currentPageIndex: Int!
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
self.pages = [
self.storyboard!.instantiateViewControllerWithIdentifier("Nav1") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("Nav2") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("Nav3") as! UINavigationController
]
(self.pages[0].topViewController as! Nav1).parentPageViewController = self
(self.pages[1].topViewController as! Nav2).parentPageViewController = self
(self.pages[2].topViewController as! Nav3).parentPageViewController = self
self.currentPageIndex = 1
let startingViewController = self.pages[1] as UINavigationController
self.setViewControllers([startingViewController], direction: .Forward, animated: false, completion: nil)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let index = (self.pages as NSArray).indexOfObject(viewController)
self.currentPageIndex = index
// if currently displaying last view controller, return nil to indicate that there is no next view controller
return (self.currentPageIndex == self.pages.count - 1 ? nil : self.pages[self.currentPageIndex + 1])
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let index = (self.pages as NSArray).indexOfObject(viewController)
self.currentPageIndex = index
// if currently displaying first view controller, return nil to indicate that there is no previous view controller
return (index == 0 ? nil : self.pages[index - 1])
}
func displayPageForIndex(index: Int, animated: Bool = true) {
assert(index >= 0 && index < self.pages.count, "Error: Attempting to display a page for an out of bounds index")
// nop if index == self.currentPageIndex
if self.currentPageIndex == index { return }
if index < self.currentPageIndex {
self.setViewControllers([self.pages[index]], direction: .Reverse, animated: true, completion: nil)
} else if index > self.currentPageIndex {
self.setViewControllers([self.pages[index]], direction: .Forward, animated: true, completion: nil)
}
self.currentPageIndex = index
}
}
It is quite easy to do. You will subclass UIWindow, add a mini-player view and make sure it is alway at the top of view hierarchy. First in your AppDelegate add this code to overwrite your window:
/*!
* Subclassing UIWindow
*/
-(UIWindow *)window
{
static YourWindow *customWindow = nil;
if (!customWindow) customWindow = [[YourWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
return customWindow;
}
And now in YourWindow class, add the miniPlayer:
-(void)awakeFromNib
{
[self addMiniPlayer];
}
-(void)addMiniPlayer
{
UIView *miniPlayer = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)]; //change to your frame here
[self addSubview:miniPlayer];
miniPlayer.backgroundColor = [UIColor redColor];
self.miniPlayer = miniPlayer;
}
-(void)layoutSubviews
{
[super layoutSubviews];
[self bringSubviewToFront:self.miniPlayer];
// You would like to update your miniplayer frame here.
//CGRect frame = self.miniPlayer.frame;
//frame.origin.x = self.frame.size.width - frame.size.width - 5;
//frame.origin.y = 70;
//self.appInfoLabel.frame = frame;
}
Now it is your job to adjust the behavior of the miniPlayer. You can access it from AppDelegate, something like this: self.window.miniPlayer
UPDATED: Here is an example written by Swift: https://github.com/sahara108/TestCustomWindow
Related
I've embedded a UIPageViewController in a UINavigationController, which in turn is embedded in a UITabBarController. I'm simply trying to make it so that the pageViewController loops through its viewControllers that are stored in an array. However every time I try to move to the next page, the first viewController snaps back into place before disappearing.
I've made the first viewController red and the second one blue and oddly enough when loading them in I'm presented with the second viewController.
This gif shows what I mean
I've tried to set up a pageViewController in the same manner in a new project and everything worked as expected so I can't see where the problem is.
import UIKit
final internal class TabBarController: UITabBarController, ApplicationLoginDelegate {
private let newsFeedTableViewController: NewsFeedTableViewController = NewsFeedTableViewController(style: UITableViewStyle.grouped)
private let substitutionPlanTableViewController: SubstitutionPlanTableViewController = SubstitutionPlanTableViewController(style: UITableViewStyle.grouped)
private let loginTableViewController: LoginTableViewController = LoginTableViewController(style: UITableViewStyle.grouped)
private let timeTableViewController: TimeTablePageViewController = TimeTablePageViewController(transitionStyle: UIPageViewControllerTransitionStyle.scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.horizontal, options: nil)
private let moreTableViewController: MoreTableViewController = MoreTableViewController(style: UITableViewStyle.grouped)
//
// MARK: - Override point
//
/**
Called after the controller's view is loaded into memory.
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView() method. You usually override this method to perform additional initialization on views that were loaded from nib files.
*/
override func viewDidLoad() {
super.viewDidLoad()
self.setUpTabBar()
}
/**
Notifies the view controller that its view is about to be added to a view hierarchy.
This method is called before the view controller's view is about to be added to a view hierarchy and before any animations are configured for showing the view. You can override this method to perform custom tasks associated with displaying the view. For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented. If you override this method, you must call super at some point in your implementation.
For more information about the how views are added to view hierarchies by a view controller, and the sequence of messages that occur, see Supporting Accessibility.
*/
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if UIApplication.boolForKey(UserDefaultKey.openSubstitutionPlanOnStartup) == true {
self.selectedViewController = self.viewControllers?[1]
}
}
//
// MARK: - Functions
//
private func setUpTabBar() {
// General
self.tabBar.tintColor = UIColor.applicationBaseColor
self.tabBar.unselectedItemTintColor = UIColor.lightGray
self.tabBar.backgroundColor = UIColor.white
// Create tab bar items
let newsFeedTabBarItem: UITabBarItem = UITabBarItem(title: "Aktuelles", image: #imageLiteral(resourceName: "News"), tag: 0)
let substitutionTabBarItem: UITabBarItem = UITabBarItem(title: "Vertretungen", image: #imageLiteral(resourceName: "SubstitutionPlan"), tag: 1)
let timeTableTabBarItem: UITabBarItem = UITabBarItem(title: "Stundenplan", image: #imageLiteral(resourceName: "TimeTable"), tag: 2)
let moreTabBarItem: UITabBarItem = UITabBarItem(title: "Entdecken", image: #imageLiteral(resourceName: "MoreMenu"), tag: 3)
// Link items and controllers
self.newsFeedTableViewController.tabBarItem = newsFeedTabBarItem
self.substitutionPlanTableViewController.tabBarItem = substitutionTabBarItem
self.loginTableViewController.tabBarItem = substitutionTabBarItem
self.timeTableViewController.tabBarItem = timeTableTabBarItem
self.moreTableViewController.tabBarItem = moreTabBarItem
// Set delegates
self.loginTableViewController.delegate = self
// Set tab bar view controllers
var viewControllers: [UIViewController] = []
if UIApplication.boolForKey(UserDefaultKey.isUserLoggedIn) == true {
viewControllers = [newsFeedTableViewController, substitutionPlanTableViewController, timeTableViewController, moreTableViewController]
} else {
viewControllers = [newsFeedTableViewController, timeTableViewController, moreTableViewController]
}
self.viewControllers = viewControllers.map({ (controller) -> UIViewController in
controller.navigationItem.largeTitleDisplayMode = .always
let navigationController = UINavigationController(rootViewController: controller)
navigationController.navigationBar.prefersLargeTitles = true
return navigationController
})
if UIApplication.boolForKey(UserDefaultKey.isUserLoggedIn) == false {
self.viewControllers?.insert(self.loginTableViewController, at: 1)
}
}
}
The UITabBarController and the UIPageViewController:
class TimeTablePageViewController: UIPageViewController, UIPageViewControllerDataSource {
private var timeTableViewControllers: [UIViewController]!
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.timeTableViewControllers = Array.init(repeating: UIViewController(), count: 2)
self.timeTableViewControllers[0].view.backgroundColor = .red
self.timeTableViewControllers[1].view.backgroundColor = .blue
self.setViewControllers([self.timeTableViewControllers[0]], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if let index = self.timeTableViewControllers.index(of: viewController) {
if viewController == self.timeTableViewControllers.first {
return self.timeTableViewControllers.last
} else {
return self.timeTableViewControllers[index - 1]
}
} else {
return nil
}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if let index = self.timeTableViewControllers.index(of: viewController) {
if viewController == self.timeTableViewControllers.last {
return self.timeTableViewControllers.first
} else {
return self.timeTableViewControllers[index + 1]
}
} else {
return nil
}
}
}
The repeatedValue parameter of Array.init(repeating repeatedValue: Array.Element, count: Int) is not a closure. It's a single object that will be used to fill the array.
The code won't call UIViewController() for each element it creates. You are creating an array that contains the same UIViewController instance two times. A view can't have two superViews, so when you scroll to the second page, the UIPageViewController adds the view of the only viewController to its view, which means that it will be removed from its view as well.
Replace
self.timeTableViewControllers = Array.init(repeating: UIViewController(), count: 2)
with
self.timeTableViewControllers = [UIViewController(), UIViewController()]
I know the error means I have a NULL pointer, but I am unsure as to WHY that is, and I assume it must be something I did wrong in my code. My index starts at 1 because I want it to start in the middle view controller which is the home page. I am trying to make a page view controller to swipe between view controllers similar to snapchat. I have the following code:
import UIKit
class PageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {
var viewControllersArray = [UIViewController]()
var pageIndex: Int?
let selectedIndex = 1
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.clearColor()
let vc1 = storyboard?.instantiateViewControllerWithIdentifier("ProfileView") as! ProfileViewController
let vc2 = storyboard?.instantiateViewControllerWithIdentifier("HomeView") as! HomeViewController
let vc3 = storyboard?.instantiateViewControllerWithIdentifier("MatchesView") as! MatchViewController
viewControllersArray.append(vc1)
viewControllersArray.append(vc2)
viewControllersArray.append(vc3)
self.dataSource = self
let pageContentViewController = self.viewControllerAtIndex(selectedIndex)
self.setViewControllers([pageContentViewController!], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil) //Error here
}
the error occurs at this line:
self.setViewControllers([pageContentViewController!], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil) //Error here
The error is as follows: "Thread 1: EXC_BAD_ACCESS(code=2, address=0x7fff58d57ff8)
Here is my viewControllerAtIndex function:
func viewControllerAtIndex(index : Int) -> UIViewController? {
if((self.viewControllersArray.count == 0) || (index >= self.viewControllersArray.count)) {
return nil
}
let pageContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as! PageViewController
pageContentViewController.pageIndex = index
return pageContentViewController
}
Here is my storyboard with the view controllers to swipe between:
Any and all help is greatly appreciated!
It looks like
func viewControllerAtIndex(index : Int) -> UIViewController? {
if((self.viewControllersArray.count == 0) || (index >= self.viewControllersArray.count)) {
return nil
}
let pageContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as! PageViewController
pageContentViewController.pageIndex = index
return pageContentViewController
}
Needs to be:
func viewControllerAtIndex(index : Int) -> UIViewController? {
if((self.viewControllersArray.count == 0) || (index >= self.viewControllersArray.count)) {
return nil
}
return viewControllersArray[index]
}
Additionally
let selectedIndex = 1
should be
let selectedIndex = 0
since 1 will refer to the second page.
Using the following code, I have a series of view controllers embedded in a page view controller that I'm swiping through. I just can't find a way to segue to another view controller via a bar button press. I'm planning on writing a separate function for each bar button icon in each view controller.
class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
private var pages: [UIViewController]!
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
self.pages = [
self.storyboard!.instantiateViewControllerWithIdentifier("FirstNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("SecondNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("ThirdNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("FourthNav") as! UINavigationController
]
let startingViewController = self.pages.first! as UIViewController
self.setViewControllers([startingViewController], direction: .Forward, animated: false, completion: nil)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let index = (self.pages as NSArray).indexOfObject(viewController)
// if currently displaying last view controller, return nil to indicate that there is no next view controller
return (index == self.pages.count - 1 ? nil : self.pages[index + 1])
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let index = (self.pages as NSArray).indexOfObject(viewController)
// if currently displaying first view controller, return nil to indicate that there is no previous view controller
return (index == 0 ? nil : self.pages[index - 1])
}
}
Change your implementation of PageViewController to the following (I made some changes in the methods you already implemented, and I added a new instance method.)
class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
private var pages: [UINavigationController]!
private var currentPageIndex: Int!
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
self.pages = [
self.storyboard!.instantiateViewControllerWithIdentifier("FirstNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("SecondNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("ThirdNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("FourthNav") as! UINavigationController
]
(self.pages[0].topViewController as! FirstViewController).parentPageViewController = self
(self.pages[1].topViewController as! SecondViewController).parentPageViewController = self
(self.pages[2].topViewController as! ThirdViewController).parentPageViewController = self
(self.pages[3].topViewController as! FourthViewController).parentPageViewController = self
self.currentPageIndex = 0
let startingViewController = self.pages.first! as UINavigationController
self.setViewControllers([startingViewController], direction: .Forward, animated: false, completion: nil)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let index = (self.pages as NSArray).indexOfObject(viewController)
self.currentPageIndex = index
// if currently displaying last view controller, return nil to indicate that there is no next view controller
return (self.currentPageIndex == self.pages.count - 1 ? nil : self.pages[self.currentPageIndex + 1])
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let index = (self.pages as NSArray).indexOfObject(viewController)
self.currentPageIndex = index
// if currently displaying first view controller, return nil to indicate that there is no previous view controller
return (index == 0 ? nil : self.pages[index - 1])
}
func displayPageForIndex(index: Int, animated: Bool = true) {
assert(index >= 0 && index < self.pages.count, "Error: Attempting to display a page for an out of bounds index")
// nop if index == self.currentPageIndex
if self.currentPageIndex == index { return }
if index < self.currentPageIndex {
self.setViewControllers([self.pages[index]], direction: .Reverse, animated: true, completion: nil)
} else if index > self.currentPageIndex {
self.setViewControllers([self.pages[index]], direction: .Forward, animated: true, completion: nil)
}
self.currentPageIndex = index
}
}
Now, in each of your child view controllers, add two pieces of code:
A property that maintains a weak reference to the parent PageViewController instance.
weak var parentPageViewController: PageViewController!
An IBAction to which you connect each of your bar button items. You may need to change the body of this method depending on how your Storyboard is set up.
#IBAction func barButtonTapped(sender: UIBarButtonItem) {
var newIndex = -1
switch sender.title! {
case "First":
newIndex = 0
case "Second":
newIndex = 1
case "Third":
newIndex = 2
case "Fourth":
newIndex = 3
default: break
}
self.parentPageViewController.displayPageForIndex(newIndex)
}
Does each controller need to be embedded in a UINavigationController? You could just have a UINavigationController embed a single UIViewController, that view controller references a pageviewcontroller and a barButtonItem, when the barButtonItem is tapped trigger an action that tells the pageviewcontroller to change indexes.
Or if you want to go with your current plan of action which is a barButtonItem in each UINavigationController, write a protocol with a delegate method didSelectBarButtonAtIndex or something, then give each UINavigationController a delegate property, have the pageviewcontroller conform to the protocol and become the delegate for each nav controller. Then when a bar button is tapped, call the delegate method, which should make the page controller change it's index.
Courtesy of Using UIPageViewController with swift and multiple view controllers, I'm embedding navigation controllers in a UIPageViewController so I can horizontally scroll thru them (like swipe nav). Problem:
When I reach the first or last nav controller, and then swipe in the opposite direction, the 2nd-to-first/last nav controller will duplicate. So I'll have 5 nav controllers. For example:
Starting at FirstNav, swipe left all the way to FourthNav. When I swipe right through the array of controllers from FourthNav, the sequence will be: ThirdNav, ThirdNav, SecondNav, FirstNav. Can anyone find out what's going on?
class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var index = 0
var identifiers: NSArray = ["FirstNav", "SecondNav", "ThirdNav", "FourthNav"]
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
let startingViewController = self.viewControllerAtIndex(self.index)
let viewControllers: NSArray = [startingViewController]
self.setViewControllers(viewControllers as [AnyObject], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
func viewControllerAtIndex(index: Int) -> UINavigationController! {
if index == 0 {
return self.storyboard!.instantiateViewControllerWithIdentifier("FirstNav") as! UINavigationController
}
if index == 1 {
return self.storyboard!.instantiateViewControllerWithIdentifier("SecondNav") as! UINavigationController
}
if index == 2 {
return self.storyboard!.instantiateViewControllerWithIdentifier("ThirdNav") as! UINavigationController
}
if index == 3 {
return self.storyboard!.instantiateViewControllerWithIdentifier("FourthNav") as! UINavigationController
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let identifier = viewController.restorationIdentifier
let index = self.identifiers.indexOfObject(identifier!)
//if the index is the end of the array, return nil since we dont want a view controller after the last one
if index == identifiers.count - 1 {
return nil
}
//increment the index to get the viewController after the current index
self.index = self.index + 1
return self.viewControllerAtIndex(self.index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let identifier = viewController.restorationIdentifier
let index = self.identifiers.indexOfObject(identifier!)
//if the index is 0, return nil since we dont want a view controller before the first one
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 0
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
}
The issue has to do with your calculation of the index variable in your pageViewController(_:viewControllerBeforeViewController:) and pageViewController(_:viewControllerAfterViewController:) methods. To simplify that logic and the overall logic of your page view controller, you should change your implementation to the following:
class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
private var pages: [UIViewController]!
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
self.delegate = self
self.pages = [
self.storyboard!.instantiateViewControllerWithIdentifier("FirstNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("SecondNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("ThirdNav") as! UINavigationController,
self.storyboard!.instantiateViewControllerWithIdentifier("FourthNav") as! UINavigationController
]
let startingViewController = self.pages.first! as UIViewController
self.setViewControllers([startingViewController], direction: .Forward, animated: false, completion: nil)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let index = (self.pages as NSArray).indexOfObject(viewController)
// if currently displaying last view controller, return nil to indicate that there is no next view controller
return (index == self.pages.count - 1 ? nil : self.pages[index + 1])
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let index = (self.pages as NSArray).indexOfObject(viewController)
// if currently displaying first view controller, return nil to indicate that there is no previous view controller
return (index == 0 ? nil : self.pages[index - 1])
}
}
You don't even need to maintain an index instance variable, and this implementation does not do so. But you could, if you wanted. This solution also instantiates a single instance of each UINavigationController instead of instantiating a new one every time the user attempts to scroll to a different page, which conserves memory and preserves the state of the view controllers as the user scrolls between them.
Please excuse the non-descriptive pages variable name. I didn't want to create a conflict with UIPageViewController's viewControllers property.
Currently i'm displaying modally a view controller, (embedded in in navigation) with a UIscrollView as subview. I would like to replace the scroll view with an UIPageViewController, but i cant resize the UIPageViewController neither displaying it modally. Solution, ideas?
This is the code that i have now:
UIViewController *viewController = [[UIViewController alloc] init];
UINavigationController *modalNav = [[UINavigationController alloc] initWithRootViewController:viewController];
UIBarButtonItem *dismiss = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:#selector(dismissModalViewControllerAnimated:)];
modalNav.navigationBar.topItem.leftBarButtonItem = dismiss;
modalNav.modalPresentationStyle = UIModalPresentationFormSheet;
View controllers can be embedded into one another by using the container view.
Remove your scroll view and put a container view in its place. You'll see that a view controller is embedded it in by default. Delete the embed segue, drag and drop a UIPageViewController into your storyboard and embed it in the container view.
It should look something like below.
The better way is to create a viewcontroller, add uipageviewcontrolller as its sub view.
Here is my code for Gallery Container Page. I made a push segue to Gallery Container Page so as to avoid navigation troubles (now the parent view controller for PageViewController is Gallery Container.)
import UIKit
class GalleryContainerPage: UIViewController,UIPageViewControllerDataSource {
private var pageViewController: UIPageViewController?
private let contentImages = ["person-icon.jpg",
"3807343799880.jpg","4701365629867.jpg","4713011921017.jpg"]
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBarHidden = false
// Do any additional setup after loading the view.
}
private func createPageViewController() {
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as! UIPageViewController
pageController.dataSource = self
if contentImages.count > 0 {
let firstController = getItemController(0)!
let startingViewControllers: NSArray = [firstController]
pageController.setViewControllers(startingViewControllers as [AnyObject], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
pageViewController!.didMoveToParentViewController(self)
self.view.addSubview(pageViewController!.view)
}
private func setupPageControl() {
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.grayColor()
appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
appearance.backgroundColor = UIColor.darkGrayColor()
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! PageItemController
if itemController.itemIndex > 0 {
return getItemController(itemController.itemIndex-1)
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! PageItemController
if itemController.itemIndex+1 < contentImages.count {
return getItemController(itemController.itemIndex+1)
}
return nil
}
private func getItemController(itemIndex: Int) -> PageItemController? {
if itemIndex < contentImages.count {
let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("ItemController") as! PageItemController
pageItemController.itemIndex = itemIndex
pageItemController.imageName = contentImages[itemIndex]
return pageItemController
}
return nil
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return contentImages.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
setupPageControl()
createPageViewController()
}
}