
繼續(xù)上一篇 開始用Swift開發(fā)iOS 10 - 18 Search Bar 和 UISearchController ,這一篇使用UIPageViewController構(gòu)建介紹頁面,與使用LaunchScreen.storyboard的啟動(dòng)頁不同。
向Storyboard中添加UIPageViewController
- 在Storyboard拖進(jìn)一個(gè)
UIPageViewController。修改相關(guān)屬性。

- 修改
UIPageViewController的 storyboard ID 為 WalkthroughController。
類似UINavigationController,UIPageViewController也是一種容器類型的控制器。這種容器類型的控制器是用來管理其它多個(gè)控制器的。

如果容器內(nèi)的控制器頁面元素類似(上圖就是這種情況),可以通過一個(gè)控制器重復(fù)利用。
設(shè)計(jì)介紹頁
- 下載介紹頁所需的圖片,拖到
Assets.xcasset。 - 拖動(dòng)一個(gè)新的View Controller到SB中(作為重復(fù)使用的控制器),做一些UI設(shè)計(jì):
- 設(shè)置背景為紅色
- 添加一個(gè)Label名為
Personalize,選擇合適的字體和大小,居中。 - 添加一個(gè)Image View,300*232,居中。
- 添加另一個(gè)Label名為
Pin your favorite restaurants and create your own food guide,282*64,行數(shù)為0,居中,選擇合適的字體和大小。 - 添加一些約束
- 設(shè)置新的View Controller的 storyboard ID 為 WalkthroughContentViewController。
最后大概如下:

創(chuàng)建WalkthroughContentViewController
創(chuàng)建
WalkthroughContentViewController類文件,繼承至UIViewController,并關(guān)聯(lián)上面添加的新View Controller。-
添加三個(gè)接口,關(guān)聯(lián)兩個(gè)Label和一個(gè)image view;添加四個(gè)變量,其中
index是指多個(gè)介紹頁的索引。@IBOutlet var headingLabel: UILabel! @IBOutlet var contentLabel: UILabel! @IBOutlet var contentImageView: UIImageView! var index = 0 var heading = "" var imageFile = "" var content = "" -
修改
viewDidLoad為:override func viewDidLoad() { super.viewDidLoad() headingLabel.text = heading contentLabel.text = content contentImageView.image = UIImage(named: imageFile) }
實(shí)現(xiàn) UIPageViewController
新建類
WalkthroughPageViewController,繼承至UIPageViewController。-
讓
WalkthroughPageViewControlle符合UIPageViewControllerDataSource協(xié)議。class WalkthroughPageViewController: UIPageViewController, UIPageViewControllerDataSource -
新建幾個(gè)變量,用于顯示介紹頁中的內(nèi)容。
var pageHeadings = ["Personalize", "Locate", "Discover"] var pageImages = ["foodpin-intro-1", "foodpin-intro-2", "foodpin-intro-3"] var pageContent = ["Pin your favorite restaurants and create your own foodguide", "Search and locate your favourite restaurant on Maps", "Find restaurants pinned by your friends and other foodies around the world"] -
實(shí)現(xiàn)
UIPageViewControllerDataSource協(xié)議的兩個(gè)方法,分別在介紹頁翻到下一個(gè)和翻到上一個(gè)時(shí)調(diào)用。contentViewController函數(shù)的作用是根據(jù)介紹頁的索引獲取不同的數(shù)據(jù)。instantiateViewController方法根據(jù)storyboard的中storyboard ID生成視圖控制器。func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { var index = (viewController as! WalkthroughContentViewController).index index -= 1 return contentViewController(at: index) } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { var index = (viewController as! WalkthroughContentViewController).index index += 1 return contentViewController(at: index) } func contentViewController(at index: Int) -> WalkthroughContentViewController? { if index < 0 || index >= pageHeadings.count { return nil } if let pageContentViewController = storyboard?.instantiateViewController(withIdentifier: "WalkthroughContentViewController") as? WalkthroughContentViewController { pageContentViewController.imageFile = pageImages[index] pageContentViewController.heading = pageHeadings[index] pageContentViewController.content = pageContent[index] pageContentViewController.index = index return pageContentViewController } return nil } -
修改
viewDidLoad:override func viewDidLoad() { super.viewDidLoad() dataSource = self if let startingViewController = contentViewController(at: 0) { setViewControllers([startingViewController], direction: .forward, animated: true, completion: nil) } }
setViewControllers方法是設(shè)置UIPageViewController管理的視圖控制器。
- 讓介紹頁在首頁顯示后跳出。 在
RestaurantTableViewControlle中添加:override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if let pageViewController = storyboard?.instantiateViewController(withIdentifier: "WalkthroughController") as? WalkthroughPageViewController { present(pageViewController, animated: true, completion: nil) } }
添加默認(rèn)頁面指示
頁面指示就是一般在頁面下用于分辨當(dāng)前是第一個(gè)頁面的幾個(gè)小點(diǎn)。
實(shí)現(xiàn)UIPageViewControllerDataSource協(xié)議的兩個(gè)方法:presentationCount(for:)表示總共有幾個(gè)小點(diǎn)(頁面)。
presentationIndex(for:)表示當(dāng)前頁面的索引。
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return pageHeadings.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
if let pageContentViewController = storyboard?.instantiateViewController(withIdentifier: "WalkthroughContentViewController") as? WalkthroughContentViewController {
return pageContentViewController.index
}
return 0
}

修改頁面指示的樣式
不用默認(rèn)的頁面指示,就要把上面兩個(gè)方法刪除,然后使用UIPageControl。
- 刪除上面實(shí)現(xiàn)的兩個(gè)方法。從對(duì)象庫中拖一個(gè)Page Control到walkthrough content view controller底部,在屬性檢查器中修改適當(dāng)屬性,并添加約束。
- 在
WalkthroughContentViewController中添加接口@IBOutlet var pageControl: UIPageControl!并與Page Control關(guān)聯(lián)。在viewDidLoad中添加pageControl.currentPage = index
添加NEXT/DONE按鈕
在walkthrough content view controller右下角添加一個(gè)按鈕名為NEXT。
-
在
WalkthroughContentViewController中添加接口,并按鈕關(guān)聯(lián)。@IBOutlet var forwardButton: UIButton! -
在
viewDidLoad中添加根據(jù)索引判斷按鈕名的代碼:switch index { case 0...1: forwardButton.setTitle("NEXT", for: .normal) case 2: forwardButton.setTitle("DONE", for: .normal) default: break } -
添加點(diǎn)擊按鈕的action,并與按鈕關(guān)聯(lián)
@IBAction func nextButtonTapped(sender: UIButton) { switch index { case 0...1: let pageViewController = parent as! WalkthroughPageViewController pageViewController.forward(index: index) case 2: dismiss(animated: true, completion: nil) default: break } } -
在
WalkthroughPageViewController中添加方法:func forward(index: Int) { if let nextViewController = contentViewController(at: index + 1) { setViewControllers([nextViewController], direction: .forward, animated: true, completion: nil) } }
完成類似下面:

但因?yàn)橹笆抢?code>RestaurantTableViewController的viewDidAppear方法顯示介紹頁的,而viewDidAppear方法是頁面顯示后就調(diào)用一下,這樣就出現(xiàn)不停進(jìn)入介紹頁。實(shí)際上只需要第一次打開app的時(shí)顯示介紹頁就可以了。
UserDefaults的使用
UserDefaults是用來管理應(yīng)用和用戶相關(guān)的設(shè)置的。也就是可以用UserDefaults存儲(chǔ)一些用戶相關(guān)的少量數(shù)據(jù),比如上面的是否看過介紹頁,也就是是否點(diǎn)擊過DONE按鈕了。
UserDefaults也是通過單例模式進(jìn)行操作的,通過類屬性standard獲取單例。
-
nextButtonTapped中點(diǎn)擊DONE按鈕時(shí)設(shè)置一個(gè)值標(biāo)志:@IBAction func nextButtonTapped(sender: UIButton) { switch index { case 0...1: let pageViewController = parent as! WalkthroughPageViewController pageViewController.forward(index: index) case 2: UserDefaults.standard.set(true, forKey: "hasViewedWalkthrough") dismiss(animated: true, completion: nil) default: break } } - 再到
RestaurantTableViewController的viewDidAppear判斷對(duì)應(yīng)key值。override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if UserDefaults.standard.bool(forKey: "hasViewedWalkthrough") { return } if let pageViewController = storyboard?.instantiateViewController(withIdentifier: "WalkthroughController") as? WalkthroughPageViewController { present(pageViewController, animated: true, completion: nil) } }
完成介紹頁。學(xué)習(xí)了UIPageViewController和UserDefaults。
代碼
Beginning-iOS-Programming-with-Swift
說明
此文是學(xué)習(xí)appcode網(wǎng)站出的一本書 《Beginning iOS 10 Programming with Swift》 的一篇記錄
系列文章目錄
- 開始用Swift開發(fā)iOS 10 - 1 前言
- 開始用Swift開發(fā)iOS 10 - 2 Hello World!第一個(gè)Swift APP
- 開始用Swift開發(fā)iOS 10 - 3 介紹Auto Layout
- 開始用Swift開發(fā)iOS 10 - 4 用Stack View設(shè)計(jì)UI
- [開始用Swift開發(fā)iOS 10 - 5 原型的介紹]
- 開始用Swift開發(fā)iOS 10 - 6 創(chuàng)建簡單的Table Based App
- 開始用Swift開發(fā)iOS 10 - 7 定制Table Views
- 開始用Swift開發(fā)iOS 10 - 8 Table View和UIAlertController的交互
- 開始用Swift開發(fā)iOS 10 - 9 Table Row的刪除, UITableViewRowAction和UIActivityViewController的使用
- 開始用Swift開發(fā)iOS 10 - 10 Navigation Controller的介紹和Segue
- 開始用Swift開發(fā)iOS 10 - 11 面向?qū)ο缶幊探榻B
- 開始用Swift開發(fā)iOS 10 - 12 豐富Detail View和定制化Navigation Bar
- 開始用Swift開發(fā)iOS 10 - 13 Self Sizing Cells and Dynamic Type
- 開始用Swift開發(fā)iOS 10 - 14 基礎(chǔ)動(dòng)畫,模糊效果和Unwind Segue
- 開始用Swift開發(fā)iOS 10 - 15 使用地圖
- 開始用Swift開發(fā)iOS 10 - 16 介紹靜態(tài)Table Views,UIImagePickerController和NSLayoutConstraint
- 開始用Swift開發(fā)iOS 10 - 17 使用Core Data