iOS 状态机GKStateMachine管理页面状态

1.概念

GKStateMachine是GameplayKit里面的API,主要用于控制游戏状态的切换时带来的场景的切换。(野外——>副本?)
不过“他山之石,可以攻玉”,只要能合理运用,未必只能局限于游戏。

2.使用

1、场景:
本人目前的公司项目是一款视频剪辑的APP,视频制作页面的UI和业务逻辑非常繁多和复杂。大分支就分为主题、音乐、剪辑、特效、滤镜。然后每个大分支下面又有很多的小分支,比如剪辑就包含变速、倒放、比例等数10个分支。

image.png

如果使用枚举类型保存状态来进行判断,那代码结构就会变的非常难以处理。所以我们就使用状态机来管理这些状态。
2、原理:
GKStateMachine(状态机)是配合GKState(状态)使用的,一个GKStateMachine掌管多个GKState。
核心其实主要两个方法:
状态机切换到某个状态的时候,当前状态的didEnterWithPreviousState该方法会被调用。同一时间,同组其他的状态的willExitWithNextState方法会被调用。
通过业务的结构,我们搭建出整体的框架,简单说就是:每个状态都由父状态携带的状态机进行管理。

image.png

3、实现:
首先我们定义基类模板:
h文件:

@interface BaseState : GKState
//共享属性(视图注意弱引用)
@property (nonatomic, weak) UIViewController *rootVC;
@property (nonatomic, strong) id commonData;
//管理次级状态的状态机
@property (nullable, nonatomic, strong) GKStateMachine *childStateMachine;

m文件

- (void)didEnterWithPreviousState:(baseState *)preState
{
    [super didEnterWithPreviousState:preState];
    NSLog(@"did enter the state: %@",self.name);
    [self loadChildStates];
    [self freeChildStates:preState];
}

//父状态在释放时,也要把子状态释放掉
- (void)freeChildStates:(XYBaseViewState *)preState
{
    preState.childStateMachine = nil;
}

- (void)willExitWithNextState:(XYBaseViewState *)nextState
{
    [super willExitWithNextState:nextState];
}

//子类继承实现
- (NSArray *)childViewStates
{
    return @[];
}

- (void)loadChildStates
{
    NSMutableArray *viewStates =  [NSMutableArray array];
    for (NSString *obj in [self childViewStates]) {
        Class class = NSClassFromString(obj);
        if (!class) continue;
        __kindof baseViewState *state = [[class alloc]init];
        //传递共享数据
        state.rootVC = self.rootVC;
      
        [viewStates addObject:state];
    }
    //子状态进状态机
    self.childStateMachine = [GKStateMachine stateMachineWithStates:viewStates];
}

然后再真正实现具体状态,这里以裁剪状态为例:

@implementation EditorClipState

- (NSArray *)childViewStates
{
    self.subStateArray =  @[@"EditClipSubScaleState",@"EditClipSubTrimState",@"EditClipSubTransitionState"];
    return  self.subStateArray;
}

- (void)didEnterWithPreviousState:(nullable GKState *)previousState
{
    [super didEnterWithPreviousState:previousState];
    
    [self initData];
    [self initSubviews];
}

- (void)initData {
    self.dataArray = @[@"1",@"2","3",@"4"].mutableCopy;
    NSLog(@"initData");
}

- (void)initSubviews
{
    //初始化界面
    [self.rootVC.view addSubview:self.collectionView];
    NSLog(@"initSubviews");
}


- (void)willExitWithNextState:(GKState *)nextState
{
    [super willExitWithNextState:nextState];

    //在这里释放资源,降低内存消耗
    [self deInitView];
    
    [self deInitData];
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
     //进入子状态
    [self.childStateMachine enterState:self.subStateArray[indexPath.row]];
}


- (void)deInitData {
    self.dataArray = nil;
}

- (void)deInitView {
    [self.collectionView removeFromSuperview];
    self.collectionView = nil;
}

这样就实现了每个状态独自管理,每个小组成员只需要维护自己的state就行了。

你可能感兴趣的:(iOS 状态机GKStateMachine管理页面状态)