浅谈父子控制器

iOS父子控制器实现示例与技巧 本文还有配套的精品资源,点击获取 简介:在iOS开发中,父子控制器(UIViewController)是构建复杂用户界面的关键组件。本文介绍父子控制器的原理与使用方法,并通过示例展示它们在自定义导航、视图切换、模块化和数据传递等场景中的应用。掌握父子控制器有助于提高代码组织性和界面的可维护性。 1. 父子控制器概念理解 当我们讨论iOS开发中的MVC架构时,... 阅读详情

一. 什么是父子控制器?

一个控制器通过addChildViewController:方法添加多个控制器,被添加的控制器称为子控制器,添加多个子控制器的控制器称为父控制器。

二. 父子控制器关系有什么作用?

(1). 父控制器处理的事件会自动传给子控制器
(2). 子控制器处理的事件会自动传给父控制器
(3). 子控制器可以通过属性parentViewController获取父控制器
(4). 父控制器可以通过属性childViewControllers获取所有子控制器
(5). A控制器添加到B控制器上后,A控制器就会被强引用,即使A控制器的view不正在显示,A控制器和A控制器的view都不会被销毁

三. 父子控制器的使用场景?

当Apple提供的框架不能满足开发者的时候,考虑重新搭建框架。比如UITabBarController的tabBar默认是在底部,想要把它放到顶部或者左边,实现起来会很困难,这时考虑到模仿UITabBarController的功能,搭建新的框架可能会更简单。

四. 父子控制器的使用原则

  1. 创建父子控制器关系的方法
    一个控制器使用addChildViewController:方法添加子控制器,就创建了父子控制器关系。

  2. 如果两个控制器的view是父子关系(不管是直接还是间接的父子关系),那么这两个控制器也应该为父子关系,即也应该代码创建父子关系
    伪代码解释:

[a.view addSubview:b.view];
[a addChildViewController:b];
// 或者
[a.view addSubview:otherView];
[otherView addSubview:b.view];
[a addChildViewController:b];

五. 搭建框架一般遇到的问题

  1. 当点击按钮切换到A界面,如果A界面之前打开过,再次切换到A界面,会重复创建A界面的控制器
    原因:每次点击A界面都创建新的控制器,再显示新的A界面。
    解决方案:通过懒加载解决控制器的重复问题,但是如果有上百个控制器就需要创建对应的上百个关于控制器的属性,这样不太好。

  2. 当点击到A界面,切换到A界面后,A界面的控制器马上被销毁,但A界面的view还存在
    原因: A界面的控制器是弱引用,刚创建完就被销毁了。
    解决方案:与问题(1)一样的解决,但创建属性时要用Strong修饰,强引用控制器。

  3. 问题(1)的解决方案里,需要创建多个对应控制器的属性
    解决方案:创建一个强引用的数组属性,用于存储每一个控制器,存入数组的控制器都会自动被强引用。

  4. 控制器之间的无法自动传递事件,比如当旋转屏幕时,父子控制器都会自动调用willRotateToInterfaceOrientation:方法
    解决方案:不使用问题(3)的解决方案,因为每一个控制器都有childViewControllers属性,它也是一个数组,可以把控制器都添加到父控制器的childViewControllers里,这样既可以解决问题(3),也可以解决问题(4)。

  5. 当多次切换界面时,控制器的view同时存在(界面是叠加存在的,只看见最上面的界面)
    解决方案:在父控制器上添加一个属性,用于保存正在显示的控制器,当每次显示之前先移除前一个控制器的view,在赋值新的控制器,在把要显示的控制器的view添加到显示界面上。
    提示:一个对象有没有被销毁,不是看它有没有被父控件或父控制器移除,而是看它有没有被强引用,不被强引用的对象系统会自动销毁。同一个控件,添加到父控件,添加一百次,也相当于添加了一次。addSubView同一个控件,相当于把它挪到最上面。改变一个控件的父控件,直接将它加到其他的控件上,会自动从原来的父控件移除

六. 模仿UITabBarController

注意:要正确运行代码,需要子控制器的索引和按钮的索引一一对应。

#import "ViewController.h"

#import "SJMOneTableViewController.h"
#import "SJMTwoViewController.h"
#import "SJMTreeViewController.h"

@interface ViewController ()

/** 存放正在显示的控制器 */
@property (nonatomic, strong) UIViewController *showingVc;

@end

@implementation ViewController

- (void)viewDidLoad {

    // 添加子控制器
    [self addChildViewController:[[SJMOneTableViewController alloc] init]];
    [self addChildViewController:[[SJMTwoViewController alloc] init]];
    [self addChildViewController:[[SJMTreeViewController alloc] init]];

    // 默认加载第一个界面
    [self btnClick:nil];

}

// 每一个按钮都调用这个事件
- (IBAction)btnClick:(UIButton *)sender {


    // 移除前一个控制器的view
    [_showingVc.view removeFromSuperview];

    NSInteger index = 0;

    if (sender == nil) {
        index = 0;
    } else {
        // 获取当前按钮的索引
        index = [sender.superview.subviews indexOfObject:sender];
    }

    // 赋值新的控制器
    _showingVc = self.childViewControllers[index];

    _showingVc.view.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);

    [self.view addSubview:_showingVc.view];
}

@end

界面:
这里写图片描述

七. 补充

添加或移除子控制器都会自动调用控制器的- (void)didMoveToParentViewController:(UIViewController *)parent方法,当添加时,参数为父控制器,当移除时,参数是nil

ios-父子控制器的简单实现.zip 父子控制器的简单实现 立即下载

相关推荐

ios-iOS篇-UI篇-仿今日头条效果父子控制器的应用.zip

仿今日头条滚动 标题效果 ,文字渐变 字体渐变

ios swift5 父子控制器

父控制器代码 // // ViewController.swift // 父子控制器 // // Created by macvivi on 2022/1/17. // import UIKit class ViewController: UIViewController { @IBOutlet var yellowView: UIView! override func viewDidLoad() { super.viewDidLoa.

baidu_40537062的博客 1394

DL-FWI基础入门培训视频学习1、2

DL-FWI基础知识

shengMio的博客 709

父子控制器

多控制器管理 UINavigationController UITabBarController 父子控制器 模仿上述两种控制器 -(IBAction)clickScoiety:(id)sender { /* 1.控制器每次都创建 2.控制器的view每次都加上去,点一下添加一次 3.控制器的view不能处理业务逻辑,控制器是局部变量 这里为什么view在,viewController却不...

superyuan567的博客 263

Oracle19c时区升级实战:从32到42版本的数据泵TSTZ报错解决方案

本文详细介绍了Oracle19c时区版本从32升级到42的实战步骤,重点解决数据泵TSTZ报错问题。通过检查时区版本、下载补丁包、应用补丁及执行升级脚本等关键操作,确保数据库时区数据更新,避免夏令时转换错误和历史时区规则不匹配等问题。文章还提供了常见问题排查和升级后的注意事项,帮助DBA高效完成时区升级任务。

n7o8p的博客 283

用UltraISO制作镜像以RAW格式刻录系统到U盘后,在Windows上无法识别的解决办法

在这篇文章中,用UltraISO制作镜像后,会使得U盘无法识别!!!那么,如何抹掉U盘的数据,格式化U盘呢?

拥抱具身智能,昇腾Ascend C 2730

iOS开发技巧之:父子控制器

父子控制器 在 iOS 开发中我们经常用到的两大父子控制器分别是:UINavigationController 和 UITabBarController。但是经常也会为了实现一些需求,自己去写一个类似于 UITabBarController 的功能,也就是点击按钮切换控制器,如图: QQ 功能都类似于 UITabBarController,点击切换控制器。只不过将 U

vkooy的博客 1535

AVEVA PDMS 二次开发之PML实战:从宏到自定义窗体的效率提升

本文详细介绍了AVEVA PDMS二次开发中PML语言的应用,从基础宏编写到高级窗体开发,全面提升工程设计效率。通过实战案例展示如何利用PML实现批量操作、流程自动化和交互优化,帮助工程师快速掌握这一强大工具。

weixin_42549451的博客 338

父子控制器总结

父子控制器主要用到下面5个方法 1、- (void)addChildViewController:(UIViewController *)childController; 添加子控制器,建立父子关系; 如果重写此方法,必须在实现中调用父类实现; 调用addChildViewController:会自动调用child的willMoveToParentViewController:方法,不

宋波的专栏 950

【Office激活】学校正版Office已激活成功仍弹出激活窗口

学校正版Office激活问题:已激活成功仍弹出激活窗口

ESCM_的博客 1万+

价值投资/指标选股(akshare)

利用akshare的数据源,可以获取所有的股票数据以及公开的财务数据,可以进行条件筛选,获取满足条件的股票。 这套模板可以用于价值投资,指标选股。选股周期为日线级别。然后结果可以邮箱发送。 import time import akshare as ak ## A 股上市公司的实时行情数据 stock_zh_a_spot_df = ak.stock_zh_a_spot() #print(stock_zh_a_spot_df) ##取前300测试 ##取前300测试 df_stock =...

qq_26742269的博客 1万+

浅谈iOS视图控制器间的关系

本文将为详细的介绍了视图控制器UIController及其子类间的两种关系——父子关系和显示与被显示关系,能够帮助初学者更好地理解tabBarController、navigationController、splitViewController、parentViewController、presentedViewController、presentingViewController等属性的含义和作用,同时对UINavigationController、UITabBarController视图控制器容器有更深

赤条条的博客 4881

OpenCV实战:用C++和Python实现亚像素边缘检测(附完整代码)

本文详细介绍了使用OpenCV实现亚像素边缘检测的技术,通过C++和Python双语言代码解析,提升工业测量和医学影像中的检测精度。文章涵盖算法原理、核心实现步骤及工业应用案例,帮助开发者掌握亚像素精度处理技术,解决高精度场景中的边缘检测难题。

beer8的博客 373

php 域控,服务器_把服务器升级为域控制器,Windows 2000包含了一个工具,DCPR - phpStudy...

把服务器升级为域控制器Windows 2000包含了一个工具,DCPROMO.EXE,它用来把一个独立/成员服务器升级为域控制器,或者反过来。在Windows 2000中,域是DNS名称,这意味着你有一个域的层次结构,也就有了父子域的关系。父-子关系的优点在于有双向的,具有传递性的委托,也就是说,如果域b是域a的子域,而域c是域b的子域,那么域c隐含着委托域a。这与Windows NT早期版本的域...

weixin_32673065的博客 231

[QMT和ptrade量化交易小白入门]-109、小市值选股的基础上用六脉神剑评分,回测年化可到132%

本专栏主要是介绍QMT和ptrade的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写200篇左右。QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。

木头大左的博客 1859

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

浅谈进程

目录 进程 什么是进程 进程的三个特征 进程与程序的区别 进程的创建 进程的三个基本状态 进程的终止 进程的层次结构 进程 什么是进程 概念:正在运行的一个过程或者一个任务,每...

weixin_38166793的博客 185

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

浅谈线程和进程

进程 什么是进程 概念:正在运行的一个过程或者一个任务,每个进程在内存中使用的数据彼此都是物理级别的隔离 进程的三个特征 独立性:进程是系统中独立存在的实体,它可以拥有自己的独立的资源,每一个进程都拥有自己的私有的地址空间。在没有经过进程本身允许的情况下, 个用户进程不可以直接访问其他进程的地址空间 动态性:进程与程序的区别在于,程序只是 个静态的指令集合,而进程是一个正在系统...

weixin_30609331的博客 181

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

浅谈SpringMVC源码的SpringServletContainerInitializer的完整加载流程

本文主要讲解的是SpringMVC不使用web.xml文件,而是使用JavaConfig的方式完成对SpringMVC配置的配置。即换一种方式完成DispatcherServlet等类的配置。 参考文章:SpringMVC 通过java类配置(不通过web.xml和xml 配置文件方式) 通过本文,你将了解到: 1. SpringMVC和Spring之间如何使用父子容器进行连接 2. SpringMVC的ServletContextListener和DispatcherServlet是在什么时候进行加载,

持续Java学习中 1328

浅谈MVC

MVC不是一个新概念,只要有一定开发经验的人基本都知道这个东东。但是之前在业界一直不温不火,直到IOS火起来,这个概念开始为人所熟识并加以运用。 究其原因,个人以为是之前的人把MVC搞复杂了(例如ASP.net MVC),IT就是这样,技术越复杂就会越难被人理解接受,越不被人理解接受,自然就不会被大家推广使用。 因为之前是搞.net开发了,有过四年asp.net开发经验,虽然说不上钻得有多深,

junbaozi的专栏 816

Redis持久化之 RDB 和 AOF 浅谈

Redis提供的持久化机制    Redis是一种面向“key-value”类型数据的分布式NoSQL数据库系统,具有高性能、持久存储、适应高并发应用场景等优势。它虽然起步较晚,但发展却十分迅速。 近日,Redis的作者在博客中写到,他看到的所有针对Redis的讨论中,对Redis持久化的误解是最大的,于是他写了一篇长文来对Redis的持久化进行了系统性的论述。 文章主要包含三个方面:Red...

weixin_41380972的博客 184

Linux内核架构浅谈65 - Linux总线系统:USB总线的热插拔与驱动加载机制

本文深入解析Linux内核中USB总线的热插拔机制与驱动加载流程。通过总线-设备-驱动三层模型,系统自动完成设备枚举、驱动匹配和资源管理。当USB设备插入时,控制器触发中断,内核通过控制传输获取设备信息并注册设备,最终由udev服务完成驱动加载。驱动通过usb_driver结构体声明支持设备,probe函数实现初始化。设备移除时执行disconnect清理资源。这种分层解耦、自动匹配的设计实现了USB设备的高效管理,体现了Linux内核的灵活性和可扩展性。

文石_2009的博客 1086

关于iOS应用管理之九宫格的坐标计算以及与UIScrollView的结合

关于九宫格的布局以及坐标的计算,对于大多数的iOS初学者甚至有一定能力的学者来说都是一大难题,在此写者通过自己的开发经验以及多次应用,把自己的所学所得分享给大家,就通过应用管理来进行浅谈一二。 1、功能分析:通过九宫格的样式添加相应的应用;当点击“下载”按钮时会执行相应的操作 2、实现步骤:1>.首先加载相应的应用信息;2>.根据应用的个数添加相对应的view...

weixin_30477797的博客 157

[ASP.NET MVC]如何設定Area底下的頁面為起始頁(網址路由Routing)

天突然收到朋友的Line : 你知道怎麼把MVC Routing設定為Area底下的頁面嗎? 當下很帥氣的回覆:在Global底下Application Start裡的Routing設定就好了阿(煙) 但其實這是很不負責的答案阿XDD 回家到電腦旁趕緊試一下! 首先要先淺談一下MVC的Area 在開發較大型的MVC網站中,通常會進行模組化的規劃,如一直在同一個Control

天外有天,人外有人。 专注品质 不断创新 让精益求精成为习惯 1374

php获取另一个php页面_post值,php接受post传值的方法

这段时间在研究php的接口,利用jmeter模拟发送数据给php服务器,看php如何接收post传输过去的数据,遇到了几个问题,经过一番度娘之后终于有所理解,记录一下:这里记录常用的两种post方式第一种:content-type为application/x-www-form-urlencoded,这是post默认的数据格式,在使用jquery的ajax来post数据的时候默认就是这种方式,这种方...

weixin_34026997的博客 853
上一篇: iOS项目小笔记
下一篇: UIScrollView的自动布局
活在生活里
博客等级 码龄11年 94粉丝 82原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值