开始用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是指多个介绍页的索引。

    @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 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中添加根据索引判断按钮名的代码:

          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)
          }
      }
    

完成类似下面:

但因为之前是利用RestaurantTableViewControllerviewDidAppear方法显示介绍页的,而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
          }
      }
    
  • 再到RestaurantTableViewControllerviewDidAppear判断对应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)
          }
      }
    

完成介绍页。学习了UIPageViewControllerUserDefaults

代码

Beginning-iOS-Programming-with-Swift

说明

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

系列文章目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容