Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example of UIPageViewController without storyboard i.e. created programmatically
// derived from https://www.veasoftware.com/posts/uipageviewcontroller-in-swift-xcode-62-ios-82-tutorial
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window!.rootViewController = ViewController()
window!.makeKeyAndVisible()
return true
}
}
struct Page {
var title: String
var image: String
}
let PAGES = [
Page(title: "Explore", image: "https://i.imgur.com/FGknouw.png"),
Page(title: "Today Widget", image: "https://i.imgur.com/feuwhEc.png"),
]
class ViewController: UIViewController {
var pageViewController: UIPageViewController!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
let pc = UIPageControl.appearance()
pc.pageIndicatorTintColor = UIColor.lightGrayColor()
pc.currentPageIndicatorTintColor = UIColor.blackColor()
pc.backgroundColor = UIColor.whiteColor()
let btn = UIButton(type: .System)
btn.setTitle("Restart", forState: .Normal)
btn.addTarget(self, action: "restartAction:", forControlEvents: .TouchUpInside)
self.pageViewController = UIPageViewController(transitionStyle: .Scroll, navigationOrientation: .Horizontal, options: nil)
self.pageViewController.dataSource = self
self.restartAction(self)
self.addChildViewController(self.pageViewController)
let views = [
"pg": self.pageViewController.view,
"btn": btn,
]
for (_, v) in views {
v.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(v)
}
NSLayoutConstraint.activateConstraints(
[NSLayoutConstraint(
item: btn,
attribute: .CenterX,
relatedBy: .Equal,
toItem: self.view,
attribute: .CenterX,
multiplier: 1,
constant: 0),
] +
NSLayoutConstraint.constraintsWithVisualFormat("H:|[pg]|", options: .AlignAllCenterX, metrics: [:], views: views) +
NSLayoutConstraint.constraintsWithVisualFormat("V:|-30-[pg]-[btn]-15-|", options: .AlignAllCenterX, metrics: [:], views: views)
)
self.pageViewController.didMoveToParentViewController(self)
}
func restartAction(sender: AnyObject) {
self.pageViewController.setViewControllers([self.viewControllerAtIndex(0)], direction: .Forward, animated: true, completion: nil)
}
func viewControllerAtIndex(index: Int) -> ContentViewController {
if (PAGES.count == 0) || (index >= PAGES.count) {
return ContentViewController()
}
let vc = ContentViewController()
vc.pageIndex = index
return vc
}
}
// MARK: - Page View Controller Data Source
extension ViewController: UIPageViewControllerDataSource {
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 == PAGES.count) {
return nil
}
return self.viewControllerAtIndex(index)
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return PAGES.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
}
class ContentViewController: UIViewController {
var pageIndex: Int!
override func viewDidLoad() {
super.viewDidLoad()
let lb = UILabel()
lb.textAlignment = .Center
lb.text = PAGES[self.pageIndex].title
let iv = UIImageView()
iv.contentMode = .ScaleAspectFit
ImageLoader.sharedLoader.imageForUrl(PAGES[self.pageIndex].image) { (image, url) -> () in
iv.image = image
}
let views = [
"iv": iv,
"lb": lb,
]
for (_, v) in views {
v.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(v)
}
NSLayoutConstraint.activateConstraints(
NSLayoutConstraint.constraintsWithVisualFormat("H:|-[lb]-|", options: .AlignAllCenterX, metrics: [:], views: views) +
NSLayoutConstraint.constraintsWithVisualFormat("H:|-[iv]-|", options: .AlignAllCenterX, metrics: [:], views: views) +
NSLayoutConstraint.constraintsWithVisualFormat("V:|-[lb]-[iv]-|", options: .AlignAllCenterX, metrics: [:], views: views)
)
}
}
class ImageLoader {
// source and license: https://github.com/natelyman/SwiftImageLoader
let cache = NSCache()
class var sharedLoader : ImageLoader {
struct Static {
static let instance : ImageLoader = ImageLoader()
}
return Static.instance
}
func imageForUrl(urlString: String, completionHandler: (image: UIImage?, url: String) -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {()in
let data = self.cache.objectForKey(urlString) as? NSData
if let goodData = data {
let image = UIImage(data: goodData)
dispatch_async(dispatch_get_main_queue(), {() in
completionHandler(image: image, url: urlString)
})
return
}
let downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: {(data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
if (error != nil) {
completionHandler(image: nil, url: urlString)
return
}
if let data = data {
let image = UIImage(data: data)
self.cache.setObject(data, forKey: urlString)
dispatch_async(dispatch_get_main_queue(), {() in
completionHandler(image: image, url: urlString)
})
return
}
})
downloadTask.resume()
})
}
}
@andreif

This comment has been minimized.

Copy link
Owner Author

commented Mar 16, 2016

Info.plist needs presence of Launch screen interface file base name (which can be just an empty string) in order to support all screen sizes.

@gerchicov-bp

This comment has been minimized.

Copy link

commented Apr 12, 2018

@adreif where is index declaration?

The second problem which allows to use this code as the example only and requires significant changes is:
extension ViewController: UIPageViewControllerDataSource {
You write an extension over all view controllers even those ones where you have never needed page view controller

@ckalbas

This comment has been minimized.

Copy link

commented Apr 27, 2018

@gerchicov-bp Actually, he's extending the custom class ViewController, not UIViewController

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.