iOS开发进阶(十一):ViewController 控制器详解

news/2024/7/20 20:13:55 标签: ios, cocoa, macos

文章目录

    • 一、前言
    • 二、UIViewController
    • 三、UINavigationController
    • 四、UITabBarController
    • 五、UIPageViewController
    • 六、拓展阅读

一、前言

iOS 界面开发最重要的首属ViewControllerViewViewControllerView的控制器,也就是一般的页面,用来管理页面的生命周期(它相当于安卓里的Activity,两者很像,但又有一些差异)。

ViewController的特点是它有好几种。一种最基本的UIViewController,和另外三种容器:UINavigationControllerUITabBarControllerUIPageViewController

所谓容器,就是它们本身不能单独用来显示,必须在里面放一个或几个UIViewController

不同容器有不同的页面管理方式和展示效果:

  • UINavigationController 用于导航栏管理页面;
  • UITabBarController 用于底部tab管理页面;
  • UIPageViewController 用于切换器管理页面;

容器还可以嵌套,比如把UITabBarController放进UINavigationController里面,这样在tab页面里,可以用启动导航栏样式的二级子页面。

二、UIViewController

这是最简单的页面,没有导航栏。

使用present方法展示,展示时从底部弹起,可以用下滑手势关闭,也可以多次启动叠加多个页面。

在这里插入图片描述

代码实现如下:

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        title = "\(self.hash)"
        var label = UIButton(frame: CGRect(x: 10, y: 100, width: 300, height: 100))
        label.setTitle("present ViewController", for: .normal)
        view.addSubview(label)
        label.addTarget(self, action: #selector(presentVC), for: .touchUpInside)
        label = UIButton(frame: CGRect(x: 10, y: 200, width: 300, height: 100))
        label.setTitle("present NavigationController", for: .normal)
        view.addSubview(label)
        label.addTarget(self, action: #selector(presentNC), for: .touchUpInside)
        label = UIButton(frame: CGRect(x: 10, y: 300, width: 300, height: 100))
        label.setTitle("push ViewController", for: .normal)
        view.addSubview(label)
        label.addTarget(self, action: #selector(pushVC), for: .touchUpInside)
        label = UIButton(frame: CGRect(x: 10, y: 400, width: 300, height: 100))
        label.setTitle("present TabbarController", for: .normal)
        view.addSubview(label)
        label.addTarget(self, action: #selector(presentTC), for: .touchUpInside)
        label = UIButton(frame: CGRect(x: 10, y: 500, width: 300, height: 100))
        label.setTitle("present PageViewController", for: .normal)
        view.addSubview(label)
        label.addTarget(self, action: #selector(presentPC), for: .touchUpInside)
    }
    @objc func presentVC() {
        let vc = ViewController()
        vc.view.backgroundColor = .darkGray
        present(vc, animated: true)
    }
    @objc func presentNC() {
        let vc = ViewController()
        vc.view.backgroundColor = .gray
        let nc = UINavigationController(rootViewController: vc)
        present(nc, animated: true)
    }
    @objc func presentTC() {
        let tc = MyTabbarController()
        tc.view.backgroundColor = .blue
        let nc = UINavigationController(rootViewController: tc)
        present(nc, animated: true)
    }
    @objc func presentPC() {
        let pc = MyPageViewController()
        pc.view.backgroundColor = .red
        let nc = UINavigationController(rootViewController: pc)
        present(nc, animated: true)
    }
    @objc func pushVC() {
        let vc = ViewController()
        vc.view.backgroundColor = .purple
        if let nc = navigationController {
            nc.pushViewController(vc, animated: true)
        } else {
            print("navigationController nil!")
        }
    }
}

三、UINavigationController

这是最常用的页面导航方式,顶部展示导航栏,有标题、返回按钮。

使用pushViewController方法展示,展示时从右往左出现,可以用右滑手势关闭,也可以多次启动叠加多个页面。

注意⚠️:UINavigationController用来管理一组UIViewController,这些UIViewController共用一个导航栏。

一般来说,UINavigationController能很好地控制导航栏上面的元素显示和转场效果。

如果需要定制导航栏元素,尽量修改UIViewController的导航栏,不要直接修改UINavigationController的导航栏。

在这里插入图片描述

四、UITabBarController

这个一般用来做主页面的展示,下面配置多个tab,用于切换页面。

在这里插入图片描述

示例代码如下:

class MyTabbarController: UITabBarController {
    init() {
        super.init(nibName: nil, bundle: nil)
        self.tabBar.backgroundColor = .gray
        let vc1 = ViewController()
        vc1.tabBarItem.image = UIImage(named: "diamond")
        vc1.tabBarItem.title = "tab1"
        vc1.view.backgroundColor = .red
        let vc2 = ViewController()
        vc2.tabBarItem.image = UIImage(named: "diamond")
        vc2.tabBarItem.title = "tab2"
        vc2.view.backgroundColor = .blue
        let vc3 = ViewController()
        vc3.tabBarItem.image = UIImage(named: "diamond")
        vc3.tabBarItem.title = "tab3"
        vc3.view.backgroundColor = .purple
        self.viewControllers = [
            vc1,
            vc2,
            vc3,
        ]
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

五、UIPageViewController

这个用来做翻页的页面,比如电子书或者广告banner。可以配置左右或上下翻译,翻页效果可以配置滚动或者模拟翻书。

viewControllerBeforeviewControllerAfter回调方法控制页面切换。viewControllerBefore方法提供当前页面的前一个页面,viewControllerAfter方法提供当前页面的后一个页面。

注意⚠️:UIPageViewController有预加载机制,它会提前加载当前页面的前后页面。但是没有实现页面缓存机制,需要在外部做缓存。

如果页面非常多,但又是同一个类的实例,那么一般创建三个实例就够了,然后在viewControllerBeforeviewControllerAfter方法里循环使用这三个。

在这里插入图片描述 在这里插入图片描述

示例代码如下:

class MyPageViewController: UIPageViewController, UIPageViewControllerDataSource {
    lazy var vcs = [
        ViewController(),
        ViewController(),
        ViewController(),
        ViewController(),
        ViewController(),
    ]
    init() {
        super.init(transitionStyle: .scroll, navigationOrientation: .horizontal)
        self.dataSource = self
        let vc1 = ViewController()
        vc1.view.backgroundColor = .red
        let vc2 = ViewController()
        vc2.view.backgroundColor = .blue
        let vc3 = ViewController()
        vc3.view.backgroundColor = .purple
        let vc4 = ViewController()
        vc4.view.backgroundColor = .gray
        vcs = [vc1,vc2,vc3,vc4
        ]
        self.setViewControllers([vcs[0]], direction: .forward, animated: false)
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        let i = (vcs.firstIndex(of: viewController as! ViewController) ?? 0) - 1
        if i < 0 {
            return nil
        }
        return vcs[i]
    }
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let i = (vcs.firstIndex(of: viewController as! ViewController) ?? 0) + 1
        if i >= vcs.count {
            return nil
        }
        return vcs[i]
    }
}

六、拓展阅读

  • 《iOS开发进阶(十):viewController生命周期讲解》

http://www.niftyadmin.cn/n/5458223.html

相关文章

Challenging BIG-Bench tasks and whether chain-of-thought can solve them阅读笔记

不是新文章哈&#xff0c;就是最近要看下思维链&#xff08;chain of thought&#xff0c;CoT&#xff09;这块&#xff0c;然后做点review。 文章链接&#xff08;2022年&#xff09;&#xff1a;https://arxiv.org/pdf/2210.09261.pdf GitHub链接&#xff1a;GitHub - suzg…

react useState的初始化函数 初始化值为props时的同步问题 | setState函数的使用与异步更新

文章目录 react setState函数useState()钩子创建state如何根据props更新state值 setState的参数是下一个状态statesetState的参数是更新函数functionsetState异步与同步合成事件setState 实现原理 react setState函数 useState()钩子创建state const [state, setState] useS…

Docker安装xxl-job并整合到SpringBoot项目

1. 创建数据库 执行如下SQL语句创建相关表 CREATE database if NOT EXISTS xxl_job default character set utf8mb4 collate utf8mb4_general_ci; use xxl_job;SET NAMES utf8mb4; CREATE TABLE xxl_job_info (id int(11) NOT NULL AUTO_INCREMENT,job_group int(11) NOT NUL…

使用Docker本地搭建蚂蚁笔记并实现无公网IP远程访问

文章目录 1. 安装Docker2. Docker本地部署Leanote蚂蚁笔记3. 安装cpolar内网穿透4. 固定Leanote蚂蚁笔记公网地址 本篇文章介绍如何使用Docker部署Leanote蚂蚁笔记&#xff0c;并且结合cpolar内网穿透实现公网远程访问本地笔记编辑并制作个人博客等。 Leanote 蚂蚁笔记是一款云…

JavaScript代理模式之四大代理

JavaScript设计模式中有一种模式为代理模式 事件代理 事件代理是代理中最常见的一种&#xff0c;也是一道实打实的高频面试题&#xff0c;它的场景是一个父元素下有多个子元素。 考虑到事务具有冒泡性&#xff0c;当我们点击a标签的时候&#xff0c;会冒泡到父级。从而被监听…

C++template之类模版进一步了解

前言&#xff1a;这一篇是在我的上一篇文章的基础上&#xff0c;再进一步所写的。 链接&#xff1a;CTemplate&#xff1c;&#xff1e;模版的介绍及深度解析-CSDN博客 一、类模板实例化 1.非类型模版参数 类型模版参数&#xff1a;就是跟在 class后面或者typename后的类型 非…

牛客竞赛语法入门班选择结构习题(重现赛)(A-L)

本篇包含&#xff1a; 1、A-比大小 2、B-卡拉兹函数 3、C-默契 4、D-整除判断 5、E-CSimplemathproblem 6、F-吃瓜群众 7、G-jyq跳格子 8、H-小名的回答 9、I-牛妹数 10、J-判断闰年 11、K-统计数据正负个数 12、L-小乐乐是否被叫家长 本篇包含考点&#xff1a; 1、取模操作 2、…

4、Jenkins持续集成-用户权限和凭证管理

文章目录 一、用户权限管理1、安装用户权限管理插件2、开启权限全局安全配置3、创建角色4、创建用户5、给用户分配角色6、创建项目测试权限二、凭证管理1、安装凭证管理插件2、安装Git插件和工具2.1 用户密码类型2.2 SSH密钥类型一、用户权限管理 利用Role-based Authorizatio…