iOS开发笔记之七十三——基于状态机的页面构建方案

2023-10-22 11:59

本文主要是介绍iOS开发笔记之七十三——基于状态机的页面构建方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

******阅读完此文,大概需要20分钟******

一、简介

在美团点评时,页面基本都是列表页、详情页这类页面,所以以UIScollView/UITableView这类可以进行信息平铺的手段搭建页面为主。我之前也输出过这种页面的一种方案iOS开发笔记之六十四——基于UIView模块化组件方案_iOS开发笔记-CSDN博客,这种基于模块化,可以横向或者纵向平铺展示的方案还有很多。然而,原来的这种方案在Vivavideo这种工具类产品家族中,发挥的余地不是很理想。大家可以看下,这种工具类的一个典型的页面:

  

从上面的截图可以看出,工具类的这种编辑页下面有三种tab,每种tab下面又有很多的工具集合,如果你用传统的做法,无怪乎就是每种工具做一次addSubview,用到时做一次present的操作展示出来,你会发现,如果这样,你的VC会膨胀到你无法想象的地步。

    所以,在此基础上,我们探索出了一种状态机进行页面构建的方案,我们采取了GameplayKit中的GKStateMachine进行管理的,当然也可以自己做一套状态机进行管理。如果使用GKStateMachine去管理页面,是可以享受到它带给你一些便利的,例如以下几个操作:

- (BOOL)canEnterState:(Class)stateClass;

- (BOOL)enterState:(Class)stateClass;

以及GKState类的几种state生命周期的几个操作:

- (void)didEnterWithPreviousState:(nullable GKState *)previousState;

- (void)willExitWithNextState:(GKState *)nextState;

当你进入/退出一种状态时,都会有相应的回调;注意,这是iOS 9之后才有的。

在此基础上,我抽象出了一层基类,代码地址在这里,GitHub - Leon0206/MDStatePageKit: this is my statemachine page solution.,这只是1.0版本,后续还会不断迭代。

二、MDStatePageKit原理

1、树形结构管理状态机

每一个状态,犹如树形结构中的一个节点,它会有父状态、兄弟状态集合、子状态集合,如下图:

它有以下几个特征,

(1)一个状态有唯一的父状态(fatherState);

(2)一个状态可以有多个兄弟状态(brotherStates),兄弟状态之间可以随便切换;

(3)一个状态可以有多个子状态(childStates),父状态可以进入自己的子状态,子状态也可以返回父状态;

这些都已经体现在抽象出的基本状态单元类BaseViewState中:

@interface MDBaseViewState : GKState@property (nonatomic, strong) UIView *fatherView;@property (nonatomic, strong) UIView *contentView;@property (nonatomic, strong) GKState *fatherState;@property (nonatomic, strong) GKStateMachine *childStates;@property (nonatomic, strong) GKStateMachine *brotherStates;@end

每个状态都持有父状态的view,便于自己的contentView的布局与展示;

2、子状态的管理

当进入某一状态时(didEnterWithPreviousState:),才会去load它对应的子状态和兄弟状态;当离开某一状态时,此状态下的view也会被remove:

- (void)didEnterWithPreviousState:(MDBaseViewState *)preState
{NSLog(@"did enter the state: %@",self.name);[self.fatherView addSubview:self.contentView];[self loadChildStates];[self freeChildStates:preState];
}/*前一个状态节点的子状态以及contentView实时释放,从而可以及时释放部分内存,尽可能做到内存轻量化
*/
- (void)freeChildStates:(MDBaseViewState *)preState
{preState.childStates = nil;
}- (void)willExitWithNextState:(MDBaseViewState *)nextState
{NSLog(@"will exit the state: %@",self.name);[_contentView removeFromSuperview];_contentView = nil;
}

当然,使用者在这也可以去扩展

3、抽象基类BaseStateViewController对状态的管理

默认进入一个VC时,它是的父状态是空或者空状态(BaseZeroViewState),它的兄弟状态集合也是空(使用者可以自己扩展);

而它的子状态,需要使用者VC实现childViewStates方法,如下:

- (NSArray *)childViewStates
{return @[@"MDHopeZeroState",@"MDHopeFirstState",@"MDHopeSecondState",@"MDHopeThirdState",];
}

基类会在viewdidload时加载属于自己的子状态,与此同时,每个子状态之间又互为兄弟状态,所以每个子状态的兄弟状态也在此时进行了初始化,如下:

- (void)loadChildStates
{NSMutableArray *viewStates = [NSMutableArray array];for (NSString *obj in [self childViewStates]) {Class class = NSClassFromString(obj);if (!class) continue;MDBaseViewState *state = [[class alloc]init];state.fatherView = self.view;state.commonDataBoard = self.commonDataBoard;[viewStates addObject:state];}self.childStates = [GKStateMachine stateMachineWithStates:viewStates];//对于每种状态,它的子状态之间,互为兄弟状态for (MDBaseViewState *state in viewStates) {state.brotherStates = self.childStates;}
}

3、使用实例

下载GitHub - Leon0206/MDStatePageKit: this is my statemachine page solution.,运行里面的example,里面有一个完整的使用demo,MDStatePageKit还在不断完善中,有好的建议可以联系我634376133@qq.com。

这篇关于iOS开发笔记之七十三——基于状态机的页面构建方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/261303

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

基于Python开发PPTX压缩工具

《基于Python开发PPTX压缩工具》在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,不便于传输和存储,所以本文将使用Python开发一个PPTX压缩工具,需要的可以了解下... 目录引言全部代码环境准备代码结构代码实现运行结果引言在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,

Redis 多规则限流和防重复提交方案实现小结

《Redis多规则限流和防重复提交方案实现小结》本文主要介绍了Redis多规则限流和防重复提交方案实现小结,包括使用String结构和Zset结构来记录用户IP的访问次数,具有一定的参考价值,感兴趣... 目录一:使用 String 结构记录固定时间段内某用户 IP 访问某接口的次数二:使用 Zset 进行

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

nginx-rtmp-module构建流媒体直播服务器实战指南

《nginx-rtmp-module构建流媒体直播服务器实战指南》本文主要介绍了nginx-rtmp-module构建流媒体直播服务器实战指南,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. RTMP协议介绍与应用RTMP协议的原理RTMP协议的应用RTMP与现代流媒体技术的关系2

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

MySQL分表自动化创建的实现方案

《MySQL分表自动化创建的实现方案》在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低,分表是一种有效的优化策略,它将数据分散存储在... 目录一、项目目的二、实现过程(一)mysql 事件调度器结合存储过程方式1. 开启事件调度器2. 创

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链