【iOS 仿写计算器】

大概思路

  • 这是第一次使用MVC模式写 ,思路就是先写UI,之后根据UI设置的Button来嵌入之前的算法完成
  • 代码的View布局用到了Masonry布局

View界面

【iOS 仿写计算器】_第1张图片

  • 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一样大小。然后半径是长宽的一半
// 设置圆形button 需要注意 要是Button必须得是正方形 (长等于宽),并且cornerRadius是长的一半(正方形的内切圆)
            // borderWidth 边框厚度
            _buttonCalculator.layer.borderWidth = 2.0;
            // cornerRadius 按钮的四周圆角
            // 半径
            _buttonCalculator.layer.cornerRadius = MaxSize / 2;
            // 裁边
            _buttonCalculator.layer.masksToBounds = YES;
  • 注意在创建的时候加上tag值
// 底部按钮
    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) {
                // 设置圆形button 需要注意 要是
                    // borderWidth 边框厚度
                _buttonCalculator.layer.borderWidth = 2.0;
                    // cornerRadius 按钮的四周圆角
                    // 半径
                _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;
                // 设置圆形button 需要注意 要是
                    // borderWidth 边框厚度
                _buttonCalculator.layer.borderWidth = 2.0;
                    // cornerRadius 按钮的四周圆角
                    // 半径
                _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
    • 子界面(View)添加代理
@property (nonatomic, assign) id <ButtonDelegate> delegate;
    • 主界面(ViewCOntroller)实现协议
@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";
        }
//        const char* Cstr = [_calString UTF8String];
//        double num =  [_modelCal transformStr:Cstr];
//        _calString = [NSString stringWithFormat:@"%f", num];
//        NSLog(@"%s", Cstr);
    } else {
        _calString = [_calString stringByAppendingString:strbutton];
    }
    _viewCal.textFiled.text = _calString;
}

关于保存写入的字符串

  • 我在ViewController界面设置了一个字符串,每当传过来button的时候调用stringByAppendingString:方法添加字符串
  • 这里刚开始写的时候有一点bug就是每次输入的字符串值显示一个,后来发现Nsstring的初始化必须放在viewDidLoad 里面加载一次,然后在初始化,这里也给AC键提供了思路,当传回的是AC的tag值的时候直接
 if (button.tag == 12) {//AC键
        _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";
        }
//        const char* Cstr = [_calString UTF8String];
//        double num =  [_modelCal transformStr:Cstr];
//        _calString = [NSString stringWithFormat:@"%f", num];
//        NSLog(@"%s", Cstr);
    } 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的理解,值得一写

你可能感兴趣的:(ios,ui,objective-c,数据结构)