1.概念
GKStateMachine是GameplayKit里面的API,主要用于控制游戏状态的切换时带来的场景的切换。(野外——>副本?)
不过“他山之石,可以攻玉”,只要能合理运用,未必只能局限于游戏。
2.使用
1、场景:
本人目前的公司项目是一款视频剪辑的APP,视频制作页面的UI和业务逻辑非常繁多和复杂。大分支就分为主题、音乐、剪辑、特效、滤镜。然后每个大分支下面又有很多的小分支,比如剪辑就包含变速、倒放、比例等数10个分支。
如果使用枚举类型保存状态来进行判断,那代码结构就会变的非常难以处理。所以我们就使用状态机来管理这些状态。
2、原理:
GKStateMachine(状态机)是配合GKState(状态)使用的,一个GKStateMachine掌管多个GKState。
核心其实主要两个方法:
状态机切换到某个状态的时候,当前状态的didEnterWithPreviousState该方法会被调用。同一时间,同组其他的状态的willExitWithNextState方法会被调用。
通过业务的结构,我们搭建出整体的框架,简单说就是:每个状态都由父状态携带的状态机进行管理。
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就行了。