Fork me on GitHub

开始用Swift开发iOS 10 - 19 使用UIPageViewController构建介绍页面

继续上一篇 开始用Swift开发iOS 10 - 18 Search Bar 和 UISearchController ,这一篇使用UIPageViewController构建介绍页面,与使用LaunchScreen.storyboard的启动页不同。

向Storyboard中添加UIPageViewController

  • 在Storyboard拖进一个UIPageViewController。修改相关属性。

  • 修改UIPageViewControllerstoryboard IDWalkthroughController

类似UINavigationControllerUIPageViewController也是一种容器类型的控制器。这种容器类型的控制器是用来管理其它多个控制器的。

如果容器内的控制器页面元素类似(上图就是这种情况),可以通过一个控制器重复利用。

设计介绍页

  • 下载介绍页所需的图片,拖到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 Controllerstoryboard IDWalkthroughContentViewController
    最后大概如下:

创建WalkthroughContentViewController

  • 创建WalkthroughContentViewController类文件,继承至UIViewController,并关联上面添加的新View Controller
  • 添加三个接口,关联两个Label和一个image view;添加四个变量,其中index是指多个介绍页的索引。

    1
    2
    3
    4
    5
    6
    7
    8
    @IBOutlet var headingLabel: UILabel!
    @IBOutlet var contentLabel: UILabel!
    @IBOutlet var contentImageView: UIImageView!

    var index = 0
    var heading = ""
    var imageFile = ""
    var content = ""
  • 修改viewDidLoad为:

    1
    2
    3
    4
    5
    6
    7
    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 
    
  • 新建几个变量,用于显示介绍页中的内容。

    1
    2
    3
    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生成视图控制器。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    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

    1
    2
    3
    4
    5
    6
    7
    8
    override func viewDidLoad() {
    super.viewDidLoad()

    dataSource = self
    if let startingViewController = contentViewController(at: 0) {
    setViewControllers([startingViewController], direction: .forward, animated: true, completion: nil)
    }
    }

setViewControllers方法是设置UIPageViewController管理的视图控制器。

  • 让介绍页在首页显示后跳出。 在RestaurantTableViewControlle中添加:
    1
    2
    3
    4
    5
    6
    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:)表示当前页面的索引。

1
2
3
4
5
6
7
8
9
10
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 Controlwalkthrough 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中添加根据索引判断按钮名的代码:

    1
    2
    3
    4
    5
    switch index {
    case 0...1: forwardButton.setTitle("NEXT", for: .normal)
    case 2: forwardButton.setTitle("DONE", for: .normal)
    default: break
    }
  • 添加点击按钮的action,并与按钮关联

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @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中添加方法:

    1
    2
    3
    4
    5
    func forward(index: Int) {
    if let nextViewController = contentViewController(at: index + 1) {
    setViewControllers([nextViewController], direction: .forward, animated: true, completion: nil)
    }
    }

完成类似下面:

但因为之前是利用RestaurantTableViewControllerviewDidAppear方法显示介绍页的,而viewDidAppear方法是页面显示后就调用一下,这样就出现不停进入介绍页。实际上只需要第一次打开app的时显示介绍页就可以了。

UserDefaults的使用

UserDefaults是用来管理应用和用户相关的设置的。也就是可以用UserDefaults存储一些用户相关的少量数据,比如上面的是否看过介绍页,也就是是否点击过DONE按钮了。
UserDefaults也是通过单例模式进行操作的,通过类属性standard获取单例。

  • nextButtonTapped中点击DONE按钮时设置一个值标志:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @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
    }
    }
  • 再到RestaurantTableViewControllerviewDidAppear判断对应key值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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)
    }
    }

完成介绍页。学习了UIPageViewControllerUserDefaults

代码

Beginning-iOS-Programming-with-Swift

说明

此文是学习appcode网站出的一本书 《Beginning iOS 10 Programming with Swift》 的一篇记录

坚持原创技术分享,您的支持将鼓励我继续创作!
  • 本文标题: 开始用Swift开发iOS 10 - 19 使用UIPageViewController构建介绍页面
  • 本文作者: AndyRon
  • 发布时间: 2017年07月30日 - 00:00
  • 最后更新: 2017年09月09日 - 13:00
  • 本文链接: http://andyron.com/2017/beginning-ios-swift-19.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!