iOS 状态模式中循环引用导致Expected a type 错误
2018-01-10 14:02
239 查看
什么状态模式?就是允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
举个栗子!你有一个类GumballMachine你在它里面定义了一个枚举State,然后给State 设置了四种状态A、B、C、D。之后在你的Machine.M类中可能会这么做if(State==A){-(void)insertQuarter;-(void)ejectQuarter;state= B; //大致是执行完2个方法以后改变状态为B
}else if(state==B){-(void)turnCrank; state = C;}
一次类推。。。 以后可能还会出现更多的状态。
这时我们可以尝试一下改变!把状态执行的方法都放到一个协议里(接口)@protocol custumState <NSObject>//状态映射为具体对象、可选实现的方法@optional@required // 必须实现的方法-(void)insertQuarter;-(void)ejectQuarter;-(void)turnCrank;-(void)dispense;@end
这时我们把枚举类型的各个状态分别对应着一个类,而这个类必须实现我们上面的这个接口,而这个类里执行的方法就是我们原来state==A下面执行的方法,例如A 对应 类MySoldState , 其实通过栗子可以看出,状态类里方法的实现和状态的切换其实是通过GumballMachine 类来实现的。#import "custumState.h"#import "GumballMachine.h"@interface MySoldState : NSObject<custumState>-(instancetype)initWithMachine:(id)gumballMachine; //这里参数用id 而不用GumballMachine* 是因为GumballMachine类里会含有MySoldState的对象,为了避免循环引用所以用id.@end
它的实现:#import "MySoldState.h"
@interface MySoldState()@property(nonatomic,strong)GumballMachine * gbm;@end
@implementation MySoldState
-(instancetype)initWithMachine:(id)gumballMachine{ self= [super init]; if (self) { self.gbm = gumballMachine; } return self;}
- (void)dispense { [self.gbm releaseBall]; if (self.gbm.count>0) { [self.gbm setState:self.gbm.noQuarterState]; } else{ [self.gbm setState:self.gbm.soldOutState]; }}
- (void)ejectQuarter { NSLog(@"noThing");}
- (void)insertQuarter { NSLog(@"you inserted a quarter"); }
- (void)turnCrank { NSLog(@"noThing");}
主要的类GumballMachine.h#import "custumState.h"#import "MySoldState.h" //举例子用的其中一个 下面的三个和这个一样#import "SoldOutState.h"#import "NoQuarterState.h"#import "HasQuarterStates.h"
@interface GumballMachine : NSObject
@property(nonatomic) id<custumState> state; //相当于枚举类型的 变量@property(nonatomic,strong) id<custumState> soldState; //实现协议的对象 相当于枚举类型里的具体类型@property(nonatomic,strong) id<custumState> soldOutState;@property(nonatomic,strong) id<custumState> noQuarterState;@property(nonatomic,strong) id<custumState> hasQuarterStates;@property(nonatomic)int count;-(void)setState:(id<custumState>)state; //用来实现状态的转换-(void)releaseBall;-(instancetype)initWithQuarter:(int)numberGumballs; //用于初始化此类@end
GumballMachine.m
@implementation GumballMachine-(instancetype)initWithQuarter:(int)numberGumballs{ self = [super init]; if (self) { _soldOutState = [[SoldOutState alloc] initWithMachine:self]; //初始化状态类 _noQuarterState = [[NoQuarterState alloc] initWithMachine:self]; _hasQuarterStates = [[HasQuarterStates alloc] initWithMachine:self]; _soldState = [[MySoldState alloc] initWithMachine:self]; _count = numberGumballs; _state = _soldOutState; //把状态对象 赋予相应的实际值 if (_count>0) { _state = _noQuarterState; } } return self;}
//投进5分钱-(void)insertQuarter{ [_state insertQuarter];}
//退回5分钱-(void)ejectQuarter{ [_state ejectQuarter];}
//转动曲柄-(void)turnCrank{ [_state turnCrank]; [_state dispense];}
-(void)setState:(id<custumState>)state{ _state = state;}
-(void)releaseBall{ NSLog(@"a gumball comes rolling out the solt.."); if (_count!=0) { _count= _count-1; }}@end
相关文章推荐
- nodejs 循环引用JSON序列化错误的解决办法:TypeError: Converting circular structure to JSON
- ios block 导致的循环引用
- iOS面试中如何优雅回答Block导致循环引用的问题
- ios开发之使用block引发循环引用导致内存泄露
- ios block常见的错误(二)——循环引用
- iOS - Block产生Memory Leaks循环引用导致的内存泄漏以及解决方案
- 【C#错误】未能添加对“LoginBLL”的引用,将此项目作为引用添加将导致循环依赖项
- IOS之循环引用
- ios- block循环引用问题
- iOS设计模式-开发思路提问(系列1:一个Button的三种状态怎样切换?)
- iOS循环引用
- 0x766f9fe8指令引用,因0xc000009c的错误状态而无法将请求的数据放入内存是什么原因,打开网页就这样.
- 关于EDM模型中多个实体之间循环引用导致保存数据失败的解决方案一例
- iOS容易造成循环引用的三种场景,就在你我身边!
- iOS-Main-(RAC演练)-循环引用
- python write()参数错误,导致报错TypeError: a bytes-like object is required, not 'str'
- Xcode引用C++头文件出现 Unknown type name 'namespace' 错误的解决方法
- iOS: ARC和非ARC下使用Block与循环引用问题
- iOS-NSTimer-pause-暂停-引用循环
- iOS Android图片显示模式比较(iOS UIViewContentMode VS Android scaleType)