大概思路
- 这是第一次使用MVC模式写 ,思路就是先写UI,之后根据UI设置的Button来嵌入之前的算法完成
- 代码的View布局用到了Masonry布局
View界面
- View界面用到了Masonry,在创建按钮的时候循环创建,提前把Button的内容存到一个数组。
- @property (nonatomic, copy) NSMutableArray* buttonArray;`
_buttonArray = [NSMutableArray arrayWithObjects:@"1", @"2", @"3", @"+", @"4", @"5", @"6", @"-", @"7", @"8", @"9", @"*", @"AC", @"(", @")", @"/", @"0", @".", @"=", nil];
- 设置圆形Button的注意事项,圆形Button的原理是正方形的的内切圆,所以设置self的时候注意width和height一样大小。然后半径是长宽的一半
_buttonCalculator.layer.borderWidth = 2.0;
_buttonCalculator.layer.cornerRadius = MaxSize / 2;
_buttonCalculator.layer.masksToBounds = YES;
for (int i = 4; i < 5; i++) {
for (int j = 0; j < 3; j ++) {
NSString* buttonString = _buttonArray[j + i*4];
_buttonCalculator = [UIButton buttonWithType:UIButtonTypeCustom];
[_buttonCalculator setTitle:buttonString forState:UIControlStateNormal];
_buttonCalculator.titleLabel.font = [UIFont systemFontOfSize:43];
[_buttonCalculator addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];
[_buttonCalculator setTitle:buttonString forState:UIControlStateNormal];
[_buttonCalculator setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
[self addSubview:_buttonCalculator];
if (j > 0) {
_buttonCalculator.layer.borderWidth = 2.0;
_buttonCalculator.layer.cornerRadius = MaxSize / 2;
_buttonCalculator.layer.masksToBounds = YES;
_buttonCalculator.tag = j + i * 4;
printf("%ld ", _buttonCalculator.tag);
[_buttonCalculator mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self).offset( -MaxSize );
make.left.equalTo(self).offset(30 + (MaxSize + 15) * j + MaxSize);
make.width.equalTo(@MaxSize);
make.height.equalTo(@MaxSize);
}];
if (j == 1) {
_buttonCalculator.backgroundColor = black;
} else {
_buttonCalculator.backgroundColor = orange;
}
} else if (j == 0) {
NSString* buttonString = _buttonArray[j + i*4];
_buttonCalculator = [UIButton buttonWithType:UIButtonTypeCustom];
[_buttonCalculator setTitle:buttonString forState:UIControlStateNormal];
_buttonCalculator.titleLabel.font = [UIFont systemFontOfSize:43];
[_buttonCalculator addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];
[_buttonCalculator setTitle:buttonString forState:UIControlStateNormal];
[_buttonCalculator setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
[self addSubview:_buttonCalculator];
_buttonCalculator.backgroundColor = black;
_buttonCalculator.layer.borderWidth = 2.0;
_buttonCalculator.layer.cornerRadius = MaxSize / 2;
_buttonCalculator.layer.masksToBounds = YES;
_buttonCalculator.tag = j + i * 4;
printf("%ld", _buttonCalculator.tag);
[_buttonCalculator mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self).offset( -MaxSize );
make.left.equalTo(self).offset(15 + (MaxSize + 15) * j);
make.width.equalTo(@(2 * MaxSize + 15));
make.height.equalTo(@MaxSize);
}];
}
}
}
}
- 循环创建的时候记得加入target事件,因为运用了MVC模式所以要把点击事件传过去,这里用到了协议传值
- 协议传值
-
@protocol ButtonDelegate <NSObject>
- (void)returnButton:(UIButton*)button;
@end
@property (nonatomic, assign) id <ButtonDelegate> delegate;
@interface calculatorViewController : UIViewController<ButtonDelegate>
- (void)returnButton:(UIButton *)button;
@end
[_viewCal initView];
_viewCal.delegate = self;
-
- 实现代理方法,根据点击Button的tag值进行运算
- (void)returnButton:(UIButton *)button {
NSLog(@"Button.currentTitle = %@", button.titleLabel.text);
NSString* strbutton = button.titleLabel.text;
if (button.tag == 12) {
_calString = [[NSString alloc] init];
} else if (button.tag == 18) {
if (_calString.length != 0 && [self kuohaoPd:_calString]) {
const char* Cstr = [_calString UTF8String];
double num = [_modelCal transformStr:Cstr];
_calString = [NSString stringWithFormat:@"%f", num];
_calString = [self removeFloatAllZeroByString:_calString];
} else {
_calString = @"ERROR";
}
} else {
_calString = [_calString stringByAppendingString:strbutton];
}
_viewCal.textFiled.text = _calString;
}
关于保存写入的字符串
- 我在ViewController界面设置了一个字符串,每当传过来button的时候调用
stringByAppendingString:
方法添加字符串 - 这里刚开始写的时候有一点bug就是每次输入的字符串值显示一个,后来发现Nsstring的初始化必须放在
viewDidLoad
里面加载一次,然后在初始化,这里也给AC键提供了思路,当传回的是AC的tag值的时候直接
if (button.tag == 12) {
_calString = [[NSString alloc] init];
}
- 否则进行判错运算,输入的字符串符合即可进行算法运算
else if (button.tag == 18) {
if (_calString.length != 0 && [self kuohaoPd:_calString]) {
const char* Cstr = [_calString UTF8String];
double num = [_modelCal transformStr:Cstr];
_calString = [NSString stringWithFormat:@"%f", num];
_calString = [self removeFloatAllZeroByString:_calString];
} else {
_calString = @"ERROR";
}
} else {
_calString = [_calString stringByAppendingString:strbutton];
}
_viewCal.textFiled.text = _calString;
}
关于四则运算Model
- 我才用了中缀转后缀然后运算,设置了数字栈和符号栈,分别入栈进行运算
typedef struct node1{
double array[n];
int size;
} stackNum;
typedef struct node2{
char array[n];
int size;
} stackSymbol;
if (array[i] == '.') {
double doubleNum = 0.1;
++i;
while (array[i] >= '0' && array[i] <= '9') {
x += ((array[i] - '0') * doubleNum);
doubleNum *= 0.1;
++i;
}
}
总结
- 界面好写,主要分清MVC各司其职
- 算法的判错是重中之重,我的思路不是阻止输入,而是对输入的表达式判错。包括了括号问题,小数点问题,除0问题等
- 这个demo加深了对MVC的理解,值得一写