1.概念
GKStateMachine是GameplayKit里面的API,主要用于控制游戲狀態(tài)的切換時(shí)帶來的場(chǎng)景的切換。(野外——>副本?)
不過“他山之石,可以攻玉”,只要能合理運(yùn)用,未必只能局限于游戲。
2.使用
1、場(chǎng)景:
本人目前的公司項(xiàng)目是一款視頻剪輯的APP,視頻制作頁(yè)面的UI和業(yè)務(wù)邏輯非常繁多和復(fù)雜。大分支就分為主題、音樂、剪輯、特效、濾鏡。然后每個(gè)大分支下面又有很多的小分支,比如剪輯就包含變速、倒放、比例等數(shù)10個(gè)分支。
如果使用枚舉類型保存狀態(tài)來進(jìn)行判斷,那代碼結(jié)構(gòu)就會(huì)變的非常難以處理。所以我們就使用狀態(tài)機(jī)來管理這些狀態(tài)。
2、原理:
GKStateMachine(狀態(tài)機(jī))是配合GKState(狀態(tài))使用的,一個(gè)GKStateMachine掌管多個(gè)GKState。
核心其實(shí)主要兩個(gè)方法:
狀態(tài)機(jī)切換到某個(gè)狀態(tài)的時(shí)候,當(dāng)前狀態(tài)的didEnterWithPreviousState該方法會(huì)被調(diào)用。同一時(shí)間,同組其他的狀態(tài)的willExitWithNextState方法會(huì)被調(diào)用。
通過業(yè)務(wù)的結(jié)構(gòu),我們搭建出整體的框架,簡(jiǎn)單說就是:每個(gè)狀態(tài)都由父狀態(tài)攜帶的狀態(tài)機(jī)進(jìn)行管理。
3、實(shí)現(xiàn):
首先我們定義基類模板:
h文件:
@interface BaseState : GKState
//共享屬性(視圖注意弱引用)
@property (nonatomic, weak) UIViewController *rootVC;
@property (nonatomic, strong) id commonData;
//管理次級(jí)狀態(tài)的狀態(tài)機(jī)
@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];
}
//父狀態(tài)在釋放時(shí),也要把子狀態(tài)釋放掉
- (void)freeChildStates:(XYBaseViewState *)preState
{
preState.childStateMachine = nil;
}
- (void)willExitWithNextState:(XYBaseViewState *)nextState
{
[super willExitWithNextState:nextState];
}
//子類繼承實(shí)現(xiàn)
- (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];
//傳遞共享數(shù)據(jù)
state.rootVC = self.rootVC;
[viewStates addObject:state];
}
//子狀態(tài)進(jìn)狀態(tài)機(jī)
self.childStateMachine = [GKStateMachine stateMachineWithStates:viewStates];
}
然后再真正實(shí)現(xiàn)具體狀態(tài),這里以裁剪狀態(tài)為例:
@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];
//在這里釋放資源,降低內(nèi)存消耗
[self deInitView];
[self deInitData];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
//進(jìn)入子狀態(tài)
[self.childStateMachine enterState:self.subStateArray[indexPath.row]];
}
- (void)deInitData {
self.dataArray = nil;
}
- (void)deInitView {
[self.collectionView removeFromSuperview];
self.collectionView = nil;
}
這樣就實(shí)現(xiàn)了每個(gè)狀態(tài)獨(dú)自管理,每個(gè)小組成員只需要維護(hù)自己的state就行了。