继续上一篇 开始用Swift开发iOS 10 - 18 Search Bar 和 UISearchController ,这一篇使用UIPageViewController
构建介绍页面,与使用LaunchScreen.storyboard
的启动页不同。
向Storyboard中添加UIPageViewController
- 在Storyboard拖进一个
UIPageViewController
。修改相关属性。
- 修改
UIPageViewController
的 storyboard ID 为 WalkthroughController。
类似UINavigationController
,UIPageViewController
也是一种容器类型的控制器。这种容器类型的控制器是用来管理其它多个控制器的。
如果容器内的控制器页面元素类似(上图就是这种情况),可以通过一个控制器重复利用。
设计介绍页
- 下载介绍页所需的图片,拖到
Assets.xcasset
。 - 拖动一个新的View Controller到SB中(作为重复使用的控制器),做一些UI设计:
- 设置背景为红色
- 添加一个Label名为
Personalize
,选择合适的字体和大小,居中。 - 添加一个Image View,300*232,居中。
- 添加另一个Label名为
Pin your favorite restaurants and create your own food guide
,282*64,行数为0,居中,选择合适的字体和大小。 - 添加一些约束
- 设置新的View Controller的 storyboard ID 为 WalkthroughContentViewController。
最后大概如下:
创建WalkthroughContentViewController
创建
WalkthroughContentViewController
类文件,继承至UIViewController
,并关联上面添加的新View Controller。-
添加三个接口,关联两个Label和一个image view;添加四个变量,其中
index
是指多个介绍页的索引。@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) }
实现 UIPageViewController
新建类
WalkthroughPageViewController
,继承至UIPageViewController
。-
让
WalkthroughPageViewControlle
符合UIPageViewControllerDataSource
协议。class WalkthroughPageViewController: UIPageViewController, UIPageViewControllerDataSource
-
新建几个变量,用于显示介绍页中的内容。
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"]
-
实现
UIPageViewControllerDataSource
协议的两个方法,分别在介绍页翻到下一个和翻到上一个时调用。contentViewController
函数的作用是根据介绍页的索引获取不同的数据。instantiateViewController
方法根据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
方法是设置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) } }
添加默认页面指示
页面指示就是一般在页面下用于分辨当前是第一个页面的几个小点。
实现UIPageViewControllerDataSource
协议的两个方法:presentationCount(for:)
表示总共有几个小点(页面)。
presentationIndex(for:)
表示当前页面的索引。
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
}
修改页面指示的样式
不用默认的页面指示,就要把上面两个方法删除,然后使用UIPageControl
。
- 删除上面实现的两个方法。从对象库中拖一个Page Control到walkthrough content view controller底部,在属性检查器中修改适当属性,并添加约束。
- 在
WalkthroughContentViewController
中添加接口@IBOutlet var pageControl: UIPageControl!
并与Page Control关联。在viewDidLoad
中添加pageControl.currentPage = index
添加NEXT/DONE按钮
在walkthrough content view controller右下角添加一个按钮名为NEXT。
-
在
WalkthroughContentViewController
中添加接口,并按钮关联。@IBOutlet var forwardButton: UIButton!
-
在
viewDidLoad
中添加根据索引判断按钮名的代码:switch index { case 0...1: forwardButton.setTitle("NEXT", for: .normal) case 2: forwardButton.setTitle("DONE", for: .normal) default: break }
-
添加点击按钮的action,并与按钮关联
@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) } }
完成类似下面:
但因为之前是利用RestaurantTableViewController
的viewDidAppear
方法显示介绍页的,而viewDidAppear
方法是页面显示后就调用一下,这样就出现不停进入介绍页。实际上只需要第一次打开app的时显示介绍页就可以了。
UserDefaults的使用
UserDefaults
是用来管理应用和用户相关的设置的。也就是可以用UserDefaults
存储一些用户相关的少量数据,比如上面的是否看过介绍页,也就是是否点击过DONE按钮了。
UserDefaults
也是通过单例模式进行操作的,通过类属性standard
获取单例。
-
nextButtonTapped
中点击DONE按钮时设置一个值标志:@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
判断对应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) } }
完成介绍页。学习了UIPageViewController
和UserDefaults
。
代码
Beginning-iOS-Programming-with-Swift
说明
此文是学习appcode网站出的一本书 《Beginning iOS 10 Programming with Swift》 的一篇记录
系列文章目录
- 开始用Swift开发iOS 10 - 1 前言
- 开始用Swift开发iOS 10 - 2 Hello World!第一个Swift APP
- 开始用Swift开发iOS 10 - 3 介绍Auto Layout
- 开始用Swift开发iOS 10 - 4 用Stack View设计UI
- [开始用Swift开发iOS 10 - 5 原型的介绍]
- 开始用Swift开发iOS 10 - 6 创建简单的Table Based App
- 开始用Swift开发iOS 10 - 7 定制Table Views
- 开始用Swift开发iOS 10 - 8 Table View和UIAlertController的交互
- 开始用Swift开发iOS 10 - 9 Table Row的删除, UITableViewRowAction和UIActivityViewController的使用
- 开始用Swift开发iOS 10 - 10 Navigation Controller的介绍和Segue
- 开始用Swift开发iOS 10 - 11 面向对象编程介绍
- 开始用Swift开发iOS 10 - 12 丰富Detail View和定制化Navigation Bar
- 开始用Swift开发iOS 10 - 13 Self Sizing Cells and Dynamic Type
- 开始用Swift开发iOS 10 - 14 基础动画,模糊效果和Unwind Segue
- 开始用Swift开发iOS 10 - 15 使用地图
- 开始用Swift开发iOS 10 - 16 介绍静态Table Views,UIImagePickerController和NSLayoutConstraint
- 开始用Swift开发iOS 10 - 17 使用Core Data