使用UIPageViewController進行多頁面管理
Do it step by step!
在制作app的引導頁的時候會用到UIPageViewController,有多個水平關系的ViewController也能夠用UIPageViewController來管理。這個例子使用的數據來自豆瓣的開放API,會使用Alamofire去請求數據,并用SDWebImage加載圖片,因此你的電腦上需要安裝有Cocoapods,方便第三方庫的引入。
前期準備
1.新建一個項目,選擇Single View Application
2.Product Name填PageViewControllerDemo,語言選擇Swift
3.右鍵點擊ViewController.swift代碼文件,將它刪掉,在彈出的提示框中選擇Move To Trash
4.使用Command + N快捷鍵新建一個文件,選擇Cocoa Touch Class
5.創建一個UIViewController的子類,將它命名為MainController。在接下來的部分,將會看到MainController的作用是用來給UIPageViewController提供相應的ViewController,并對頁面改變做出響應。
6.打開Main.storyboard,現在只有一個Scene在Main.storyboard中,選中這個scene讓它和MainController.swift代碼文件關聯
暫時把項目關掉,引入第三方庫之后,再重新打開。
接下來我們開始使用Cocoapods引入Alamofire和SDWebimage
7.使用終端進入項目所在的目錄,使用cd <項目路徑>命令,回車之后就進入了項目所在目錄
8.在終端敲入這條命令touch Podfile,回車,這樣就創建了Podfile文件
9.打開項目文件夾,你會發現多了一個Podfile文件,雙擊打開Podfile,將下面這段安裝命令復制到Podfile中
platform :ios, '8.0'
use_frameworks!
pod 'Alamofire'
pod 'SDWebImage'
10.關閉Podfile,回到終端,在終端里面敲入pod install命令,回車,安裝第三方庫。
等待....安裝完成之后,會有和截圖類似結果。
請注意終端里的最后一句綠色的文字,它說從現在開始要使用PageViewControlerDemo.xcworkspace來打開項目了,因此以后打開這個項目時不能再使用雙擊PageViewControlerDemo.xcodeproj的方式。
布局階段
1.打開項目,并打開storyboard,選中MainController,將它嵌入到NavigationController中。
2.從控件庫中拖3個Button到MainController,把它們平鋪在navigationBar的下方,這些Button用來切換不同的頁面。
3.同時選中這3個Button,改變它們的一些屬性
屬性 | 相應的值 |
---|---|
寬度 高度 | 200,40 |
背景顏色 | RGB(248, 248, 248) |
字體顏色 | 黑色 |
完成之后,如下所示
4.接下來為button添加約束,以下是我們需要實現的約束
- button位于navigationBar的正下方
- 每個button的寬度為屏幕寬度的1/3
- 每個button等高等寬
- 彼此相鄰
選中最左邊的button,點擊設計面板右下方的第三個按鈕,給它添加左邊,上邊,以及高度這三個約束
按住control鍵,用鼠標左鍵從button中往空白處拖,可以看到一條藍色的線,松開鼠標左鍵,在彈出菜單中選擇Equal Widths
我們要button的寬度為屏幕的1/3,而不是完全等于屏幕寬度,因此要修改一個系數,在Document outline中選中Botton.width約束,將Multiplier改為1/3
接下來為剩下的兩個button添加約束,選中第二個button,按住control鍵,用鼠標左鍵向第一個button拖,放開左鍵,按住shift鍵,在彈出菜單中選擇Horizontal Spacing,Top,Equal Widths,Equal Heights,最后點擊Add Constraints
最后一個button也用同樣的方法給它加上約束
最后在不同的模擬器運行一遍看看有什么效果,或者用預覽的方式看也行。可以看到button是均勻排列的
5.添加當前頁面提示條,在button的下方會有一個紅色的條,用來提醒當前是哪個頁面,順便把的button的Title分別改為(電影,音樂,圖書),因為使用了豆瓣的API獲取了這三種不同的數據。
首先從控件庫里面拉一個View到button的下方,為了看的清楚一點,給View的設置一個深一點的背景色,選中它,添加以下4個約束,在Update Frames選擇Items of New Constraints,最后點添加
6.在MainController中嵌入一個UIPageViewController,讓UIPageViewController成為MainController的SubViewController,執行以下的5個操作
- 從控件庫中找到Container View,并把它拖到MainController的空白處
- 會發現多了一個ViewController,把它刪掉
- 選中Container View,給它添加上下左右都為0的4個約束
- 從控件庫中找到Page View Controller,并把它拖到設計面板的空白處
- 選中Container View,按住control鍵,用鼠標左鍵向第一個Page View Controller拖,放開左鍵,從彈出菜單中選擇Embed
經過上面的5個步驟,就把Page View Controller嵌入到MainController中了,這個過程也可以用代碼來實現的。下面是完成之后的截圖
7.接下開是3個真正要展示內容的頁面,因為3個頁面的布局一摸一樣,因此只把第一個頁面的步驟記下來,剩下的兩個是相同的。
在控件庫中拖一個View Controller到設計面板的空白處,選中這個剛添加的View Controller,把它的Storyboard ID設置為MovieControllerID
在這個View Controller中添加一個TableView,改變TableView的大小,讓它鋪滿整個View Controller,然后點擊設計面板右下方的最后一個布局按鈕,在彈出菜單中選擇Add Missing Constraints
這時新建一個代碼文件和這個View Controller關聯起來。Command + N,選擇Cocoa Touch Class,創建一個UIViewController的子類,把它命名為MovieController,最后回到storyboard把View Controller和MovieController關聯起來,這樣就可以在MovieController.swift代碼文件中添加代碼來控制相應的View Controller
8.執行第7步的內容,創建接下來的兩個頁面,對應如下
StoryBoard ID | 代碼文件名 | 關聯的View Controller |
---|---|---|
MovieControllerID | MovieController.swift | Movie Controller |
MusicControllerID | MusicController.swift | Music Controller |
BookControllerID | BookController.swift | Book Controller |
完成后代碼文件的結構,以下是完成上面步驟后的代碼文件結構圖,和storyboard截圖
還差一點點,布局工作就要完成了,加油?。。。?br> 9.創建一個通用的UITableViewCell的子類,用來顯示圖片的標題。創建一個新的文件,同樣選擇Cocoa Touch Class,不過這次要繼承UITableViewCell,把它命名為CommonCell,同時勾選Also create XIB file
10.打開CommonCell.xib,將Common Cell的高度設置為150
11.為Common Cell添加Image View和Label。執行以下步驟
- 拖放一個Image View到Common Cell中,將它的寬高分別設置為120,150
- 給Image View添加如下約束
- 拖放一個Label到Common Cell中
- 給Label添加如下約束,并把它的文字設置為居中
完成之后
12.選中Common Cell,打開輔助視圖,為Image View和Label生成相應的outlet。Image View對應的outlet為coverImageView,Label對應的outlet為titleLabel
13.回到storyboard分別為Movie Controller,Music Controller,BookController的tableView生成相應的outlet。
View Controller | Table View Outlet |
---|---|
Movie Controller | movieTableView |
Music Controller | musicTableView |
Book Controller | bookTableView |
14.選中MainController的button,從左到右依次把它們的tag設置為100,101,102
到這里為止所有的布局就結束了,接下來就是代碼部分了!
代碼環節
在寫代碼之前,先創建幾個分組,方便代碼的分類和管理。右鍵點擊PageViewControllerDemo分組,選擇New Group,輸入新的分組名Controller。用同樣的方式創建以下5個分組,View,DataModel,Other,Storyboard & XIB,Helper。
分組是組織代碼的一種方式,把具有相似功能的代碼放到一個分組中。完成后,代碼文件結構會和下面的截圖類似
現在開始寫代碼
1.右鍵Helper分組,新建一個SWift File,把它命名為GetDataFromDouBan
import Alamofire //導入Alamofire, 以便執行網絡請求
class GetDataFromDouBan {
/**
用來從豆瓣開放平臺中獲取數據的幫助方法
- parameter dataURL: 請求URL(對應電影,音樂,圖書的請求地址)
- parameter type: 類型分別是subjects,musics,books
- parameter keyword: 搜索關鍵字
- parameter completedHandle: 數據接收到之后的處理函數
*/
static func getData(dataURL: String, type: String, keyword: String, completedHandle: (data: [NSDictionary]) -> Void) {
//請求數據
Alamofire.request(.GET, dataURL, parameters: ["q": keyword, "count": "10"], encoding: ParameterEncoding.URL, headers: nil).responseJSON { (response: Response<AnyObject, NSError>) -> Void in
//獲取返回的內容
if let result = response.result.value {
//拿到電影,音樂,圖書的信息
if let data = result[type] as? [NSDictionary] {
//回到主線程,執行UI更新等操作
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
completedHandle(data: data)
})
}
}
}
}
}
上面的代碼看不懂也沒有關系,它的作用是用來獲取電影,音樂,圖書等數據的,拿到數據之后,就會執行completedHandle(data: data)函數,進行數據模型的搭建,UI的刷新等
2.回到MainController.swift代碼文件,這是我們的主控制器。首先添加一個屬性,通過這個屬性來引用我們嵌入到Main Controller的UIPageViewController
var pageViewController: UIPageViewController!
在viewDidLoad()方法中,添加下面這句代碼。它獲取MainController的所有子視圖控制器,因為只有一個,所以第一個就是UIPageViewController
//獲取到嵌入的UIPageViewController
pageViewController = self.childViewControllers.first as! UIPageViewController
在pageViewController屬性的下面添加3個變量,以此來引用在前面創建的3個頁面
var pageViewController: UIPageViewController!
var movieController: MovieController!
var musicController: MusicController!
var bookController: BookController!
在viewDidLoad()方法中對這3個變量進行初始化,分別對應電影,音樂,圖書頁面
//根據Storyboard ID來創建一個View Controller
movieController = storyboard?.instantiateViewControllerWithIdentifier("MovieControllerID") as! MovieController
musicController = storyboard?.instantiateViewControllerWithIdentifier("MusicControllerID") as! MusicController
bookController = storyboard?.instantiateViewControllerWithIdentifier("BookControllerID") as! BookController
UIPageViewController是容器控制器,可是它自己卻不知道應該包含哪些View Controller,所以要有別人來告訴它。借助UIPageViewControllerDataSource中的兩個方法,告訴UIPageViewController應該在頁面切換的時候,顯示什么內容。在最后一個花括號的下方添加下面這段代碼
extension MainController: UIPageViewControllerDataSource {
//返回當前頁面的下一個頁面
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
if viewController.isKindOfClass(MovieController) {
return musicController
}
else if viewController.isKindOfClass(MusicController) {
return bookController
}
return nil
}
//返回當前頁面的上一個頁面
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
if viewController.isKindOfClass(MusicController) {
return movieController
}
else if viewController.isKindOfClass(BookController) {
return musicController
}
return nil
}
}
接著回到viewDidLoad()方法,在它的最下方,添加兩行代碼,代碼的作用可以從注釋中看出
//設置pageViewController的數據源代理為當前Controller
pageViewController.dataSource = self
//手動為pageViewController提供提一個頁面
pageViewController.setViewControllers([movieController], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
運行程序看看有什么效果,可以看到,用鼠標或者用手指(真機調試)左右滑動屏幕,有翻書的效果。到這里已經成功一半了,不過翻書的效果不是這里想要的,回到storyboard,找到Page View Controller,修改它的一個屬性。
這里將Transition Style改為了scroll,這樣做之后,頁面之間的切換效果就變成水平滑動了。
是時候為電影,音樂,圖書這3個頁面填充點內容了
3.右鍵點擊DataModel分組,新建一個Swift File,把它命名為CommonDataModel,在這個文件聲明一個結構體,作為基本的數據模型
/**
* 基本數據模型, 包含圖像地址和標題
*/
struct CommonDataModel {
var imageURL: String!
var title: String
init(imageURL: String, title: String) {
self.imageURL = imageURL
self.title = title
}
}
這個結構體很簡單,一個存儲圖像地址的變量imageURL,和一個存儲標題的變量title,還有一個構造方法
4.右鍵點擊DataModel分組,創建3個Swift File文件,分別命名為MovieResults,MusicResults,BookResults。打開MovieResults.swift文件,添加下面這段代碼
class MovieResults {
//存儲電影信息的數組
var movies = [CommonDataModel]()
init(dicts: [NSDictionary]) {
//遍歷字典數組,拿到圖像地址,標題信息
//接著使用CommonDataModel創建一條電影記錄
for dict in dicts {
let imageURL = (dict["images"] as! NSDictionary)["large"] as! String
let title = dict["title"] as! String
let movie = CommonDataModel(imageURL: imageURL, title: title)
movies.append(movie)
}
}
}
這是存儲電影結果的類,movies變量用來保存電影記錄,從豆瓣平臺返回的數據經過解析之后,電影信息就是一個字典數組,因此這里遍歷字典數組來創建電影記錄,并添加到movies數組中
5.存儲音樂結果和圖書結果的類,和MovieResults類似?,F在分別在MusicResults.swift和BookResults.swift文件中,添加下面的兩段代碼。
class MusicResults {
var musics = [CommonDataModel]()
init(dicts: [NSDictionary]) {
for dict in dicts {
let imageURL = dict["image"] as! String
let title = dict["title"] as! String
let music = CommonDataModel(imageURL: imageURL, title: title)
musics.append(music)
}
}
}
class BookResults {
var books = [CommonDataModel]()
init(dicts: [NSDictionary]) {
for dict in dicts {
let imageURL = (dict["images"] as! NSDictionary)["large"] as! String
let title = dict["title"] as! String
let book = CommonDataModel(imageURL: imageURL, title: title)
books.append(book)
}
}
}
6.接著打開MovieController.swift文件,聲明一個MovieResult類型的實例變量,添加在movieTableView outlet的下方
@IBOutlet var movieTableView: UITableView!
var movieResults: MovieResults?
7.在import UIKit的下方添加一個import語句
import SDWebImage
,這條語句引入了SDWebImage模塊,借助它可以方便的加載網絡圖片
8.為movieTableView注冊一個可重用的Cell,這個Cell就是前面用XIB文件中的樣子。把下面這段代碼添加到viewDidLoad()方法中
movieTableView.registerNib(UINib(nibName: "CommonCell", bundle: nil), forCellReuseIdentifier: "CommonCell")
9.實現UITableViewDataSource的方法,為movieTableView提供數據,在最后一個花括號的地方,添加下面這段代碼
extension MovieController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let result = moviesResult {
return result.movies.count
}
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let movie = moviesResult!.movies[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("CommonCell", forIndexPath: indexPath) as! CommonCell
cell.coverImageView.sd_setImageWithURL(NSURL(string: movie.imageURL))
cell.titleLabel.text = movie.title
return cell
}
}
- 上面的代碼比較容易看懂,如果moviesResult是nil的話,返回的行數為0,不是nil的話就返回movies記錄的數量。
- 在func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 方法中拿到對應的電影記錄,根據ReuseIdentifier從cell的重用池中獲取想要的Cell類型,這里是在前面創建的CommonCell。
- 接著為cell填充圖片和標題
10.在viewDidLoad()方法中設置movieTableView的數據源代理為當前類
movieTableView.dataSource = self
11.到現在為止都還沒有去獲取豆瓣上的數據,接下來就去獲取豆瓣上的數據,看可不可以在movieTableView中顯示出來。在在viewDidLoad()方法的最下面添加下面這段代碼
GetDataFromDouBan.getData("https://api.douban.com/v2/movie/search", type: "subjects", keyword: "張藝謀") { (data) -> Void in
self.movieResults = MovieResults(dicts: data)
self.movieTableView.reloadData()
}
借助幫助類GetDataFromDouBan的靜態方法getData()去獲取電影數據
運行之后,可以看到和下面截圖類似的結果
11.看到這個說明離成功只有一步之遙了,只是cell的高度太小了,接著實現UITableViewDelegate中的方法,來調整cell的高度。在MovieController.swift文件的最下方,添加這段代碼
//MARK: - UITableViewDelegate
extension MovieController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 150
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
最后在回到viewDidLoad()方法,在movieTableView.dataSource = self的下面,添加一句代碼,設置movieTableView的代理為當前類
movieTableView.delegate = self
再運行一次看看效果,比上一次好多了
此時整個MovieController.swift代碼文件的內容,應該和下面的類似
import UIKit
import SDWebImage
class MovieController: UIViewController {
@IBOutlet var movieTableView: UITableView!
var movieResults: MovieResults?
override func viewDidLoad() {
super.viewDidLoad()
movieTableView.registerNib(UINib(nibName: "CommonCell", bundle: nil), forCellReuseIdentifier: "CommonCell")
movieTableView.dataSource = self
movieTableView.delegate = self
GetDataFromDouBan.getData("https://api.douban.com/v2/movie/search", type: "subjects", keyword: "張藝謀") { (data) -> Void in
self.movieResults = MovieResults(dicts: data)
self.movieTableView.reloadData()
}
}
}
//MARK: - UITableViewDataSource
extension MovieController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let result = movieResults {
return result.movies.count
}
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let movie = movieResults!.movies[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("CommonCell", forIndexPath: indexPath) as! CommonCell
cell.coverImageView.sd_setImageWithURL(NSURL(string: movie.imageURL))
cell.titleLabel.text = movie.title
return cell
}
}
//MARK: - UITableViewDelegate
extension MovieController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 150
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
12.實現了一個頁面,接下來就好辦多了,因為剩下的兩個頁面幾乎一摸一樣,下面分別是MusicController.swift和BookController.swift代碼文件的內容
import UIKit
class MusicController: UIViewController {
@IBOutlet var musicTableView: UITableView!
var musicResults: MusicResults?
override func viewDidLoad() {
super.viewDidLoad()
musicTableView.registerNib(UINib(nibName: "CommonCell", bundle: nil), forCellReuseIdentifier: "CommonCell")
musicTableView.dataSource = self
musicTableView.delegate = self
GetDataFromDouBan.getData("https://api.douban.com/v2/music/search", type: "musics", keyword: "梁靜茹") { (data) -> Void in
self.musicResults = MusicResults(dicts: data)
self.musicTableView.reloadData()
}
}
}
extension MusicController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let result = musicResults {
return result.musics.count
}
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let music = musicResults!.musics[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("CommonCell", forIndexPath: indexPath) as! CommonCell
cell.coverImageView.sd_setImageWithURL(NSURL(string: music.imageURL))
cell.titleLabel.text = music.title
return cell
}
}
extension MusicController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 150
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
import UIKit
class BookController: UIViewController {
@IBOutlet var bookTableView: UITableView!
var bookResults: BookResults?
override func viewDidLoad() {
super.viewDidLoad()
bookTableView.registerNib(UINib(nibName: "CommonCell", bundle: nil), forCellReuseIdentifier: "CommonCell")
bookTableView.dataSource = self
bookTableView.delegate = self
GetDataFromDouBan.getData("https://api.douban.com/v2/book/search", type: "books", keyword: "swift") { (data) -> Void in
self.bookResults = BookResults(dicts: data)
self.bookTableView.reloadData()
}
}
}
extension BookController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let result = bookResults {
return result.books.count
}
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let music = bookResults!.books[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("CommonCell", forIndexPath: indexPath) as! CommonCell
cell.coverImageView.sd_setImageWithURL(NSURL(string: music.imageURL))
cell.titleLabel.text = music.title
return cell
}
}
extension BookController: UITableViewDelegate {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 150
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
幾乎和MovieController.swift的代碼內容一摸一樣,只是請求數據的地方不同。運行后,左右滑動,能夠在電影,音樂,圖書頁面之間切換。
13.這個demo就快要完成了,最后只剩下裝點的當前頁面提示條了。找一張條形圖片來當作提示條,把它拖到圖片資源文件夾中,把圖片命名為slider
14.回到storyboard找到Main Controller,我們的主控制器,打開輔助視圖,為包含提示條的View生成對應的outlet,把它命名為sliderView
15.為3個button生成一個Action,這個3個button都會出發這個Action,因為button的tag屬性有不同的值,所以根據tag值,可以知道點擊了哪個button。選中電影button,按住control鍵,用鼠標左鍵拖向代碼視圖中,生成相應的action,把action命名為changeCurrentPage。完成后把另外兩個button也關聯到這個action
16.回到MainController.swift代碼文件中,把提示條添加到頁面中
- 在viewDidLoad()方法的上方添加一個變量,引用提示條圖片
var sliderImageView: UIImageView!
- 在viewDidLoad()方法中的最下方,添加下面這段代碼,把提示條添加到頁面上
//添加提示條到頁面中
sliderImageView = UIImageView(frame: CGRect(x: 0, y: -1, width: self.view.frame.width / 3.0, height: 3.0))
sliderImageView.image = UIImage(named: "slider")
sliderView.addSubview(sliderImageView)
運行可以看到,提示條已經成功添加上去了 
17.為了能夠正確的使用button切換不同的頁面,以及同步提示條的位置,需要兩個變量來記錄當前頁面和上一個頁面的索引,還要一個包含3個頁面的數組
在bookController實例變量的下方聲明一個數組變量
var bookController: BookController!
var controllers = [UIViewController]() //添加的代碼
在viewDidLoad()方法中把3個頁面添加到數組中
//把頁面添加到數組中
controllers.append(movieController)
controllers.append(musicController)
controllers.append(bookController)
接著在viewDidLoad()方法的上方添加兩個變量,索引當前頁面和上一個頁面
var lastPage = 0
var currentPage: Int = 0 {
didSet {
//根據當前頁面計算得到便宜量
//一個微小的動畫移動提示條
let offset = self.view.frame.width / 3.0 * CGFloat(currentPage)
UIView.animateWithDuration(0.3) { () -> Void in
self.sliderImageView.frame.origin = CGPoint(x: offset, y: -1)
}
//根據currentPage 和 lastPage的大小關系,控制頁面的切換方向
if currentPage > lastPage {
self.pageViewController.setViewControllers([controllers[currentPage]], direction: .Forward, animated: true, completion: nil)
}
else {
self.pageViewController.setViewControllers([controllers[currentPage]], direction: .Reverse, animated: true, completion: nil)
}
lastPage = currentPage
}
}
currentPage有一個屬性觀察器,當currentPage的值被設置之后,改變提示條的位置,并根據currentPage 和 lastPage的大小關系,設置頁面的切換方向(前進,后退)
18.設置currentPage的值,找到changeCurrentPage(sender: UIButton) action,在里面添加一句代碼
//button的tag分別為100,101,102,減去100之后就對應頁面的索引
currentPage = sender.tag - 100
這時運行一遍看看,點擊不同的按鈕可以切換到不同的頁面,提示條也會跟著移動
此時還有一個問題,當滑動屏幕進行頁面切換時,提示條沒有跟著移動。
19,解決最后的問題------使用通知
打開MovieController.swift代碼文件,在viewDidLoad()方法的下方,添加一個方法,這個方法會在頁面出現時調用,在這個方法中發送一個頁面改變的通知
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//發送一個名字為currentPageChanged,附帶object的值代表當前頁面的索引
NSNotificationCenter.defaultCenter().postNotificationName("currentPageChanged", object: 0)
}
在MusicController.swift和BookController.swift代碼文件中添加相同的代碼,不過把object的值分別改為1和2
20.回到MainController.swift代碼文件,讓MainController接收頁面改變的通知,并對頁面改變作出響應。把下面的代碼添加viewDidLoad()方法中
//接收頁面改變的通知
NSNotificationCenter.defaultCenter().addObserver(self, selector: "currentPageChanged:", name: "currentPageChanged", object: nil)
在接收到通知之后,會調用currentPageChanged(notification: NSNotification)方法,接下來,添加這個方法,在這個方法中設置currentPage的值
//通知響應方法
func currentPageChanged(notification: NSNotification) {
currentPage = notification.object as! Int
}
運行可以看到,滑動屏幕進行頁面切換,提示條也會跟著移動
到這里這個demo就結束了,不是很難_ !!
總結
在這個demo中可以看到,多個水平層次的頁面能夠用UIPageViewController方便的管理。雖然這里的頁面的布局和邏輯代碼都幾乎一樣,可是卻是各自獨立的,這意味著,每個頁面可以有不同的布局方式,不同的邏輯控制,而UIPageViewController僅僅是控制頁面的切換,不會對頁面自身造成影響。