上一节我们分析了一个简单的计算器应用程序的功能需求和一些注意事项。现在,我们可以通过Xcode新建一个项目进行编码了。

 

  选择View-BasedApplication项目模板,命名为Calculator。对于CalculatorAppDelegate.h和CalculatorAppDelegate.m这两个文件我们不必作任何改动。

 

  打开CalculatorViewController.h文件,我们要定义好类的接口,包括变量和方法:

 

       首先我们需要有一个区域用来显示我们的结果,在这里我们用苹果UIKit里的TextFeild控件显示就可以了;另外我们还需要一个左操作数和运算符两个变量(请读者想一下为什么不需要记录右操作数的变量?);然后我们还需要定义一个buttonClicked方法,处理我们的按钮点击操作。这里与IBOutlet语句对应的还有一个@property语句,它的作用是声明属性(可参见上一篇Objective-C语法特性)。

 

ios科学计算器代码 iphone计算器代码_控件

 

  打开CalculatorViewController.xib文件,计算器的界面可以在这上面设计,如图所示:.

   

ios科学计算器代码 iphone计算器代码_操作数_02

  上方是一个UITextField控件,用于显示我们的输入和计算结果,底下是各个运算和数字按钮,双击按钮即可更改按钮上的字符(如果想更加美观,还可以为按钮制作背影图片),调整好各按钮的大小并对齐。

 

       注意到刚才在CalculatorViewController.h文件中,我们对display变量和buttonClicked操作分别用了IBOutlet和IBAction关键字。这里的IB前缀就是代表Interface Buider,只有这样定义之后,它们才能与nib文件连接起来。具体的连接方法如下:

 

       连接输出口:按下Control键,单击nib主窗口中的File’s Owner图标,拖拉至View窗口UITextField控件之上(此时会看到一条蓝色的细线被拉出来),然后释放鼠标,从弹出来的Outlet列表中选择display变量。

ios科学计算器代码 iphone计算器代码_ios科学计算器代码_03

 

 

       指定操作:按住Control件不放,左击某个按钮拖放到File’s Owner图标上,即可从Event列表下选择buttonClicked。

ios科学计算器代码 iphone计算器代码_操作数_04

 

 

       上面这种方法虽然简单直观,但只能处理Touch up inside事件。更一般的方法是调出连接检查器,从Event事件列表下相应的事件后面圆圈里点击拖放到File’s Owner下,再选择对应的操作。选择之后可以看到连接检查器下就增加了一个事件的连接(删除连接点击File’s Owner前的叉号即可)。

 

ios科学计算器代码 iphone计算器代码_控件_05

 

  将全部18个按钮的点击事件都连接好后,就可以打开CalculatorViewController.m文件编写我们的程序实现代码了。

 

       首先我们要添加语句 @synthesize display;

       它与CalculatorViewController.h下的 @property 语句对应,为display属性自动生成访问方法(getter)和修改方法(setter)。同时,我们需要在viewDidUnload方法中将display变量置为nil,并在dealloc方法中对display变量发送release消息,使程序能在结束时能自动释放变量占用的内存。

 

       另外,我们在viewDidLoad方法中增加一些初始化的操作:

 

      

display.text= @”0”;
       operator= @”=”;
       bBegin= YES;

 

  接下来,我们要重点处理的就是buttonClicked方法了。

  我们先根据参数sender获得点击按钮对象:

 

 

UIButton *btn =(UIButton *)sender;

 

  因为我们确认点击的都是按钮,所以这句话一定可以给我们正确返回一个按钮的实例。但我们怎么知道点击的是哪个按钮呢?比较容易想到的一个方法就是根据按钮上的字符来区分。但考虑到点击各种操作符的处理都不一样,如果都靠if…else…来判断,未免让代码看起来太臃肿。在这里,我们选择使用switch来作分支的开关。遗憾的是,Objective-C中的switch变量只能是int型而不能是string型,所以我们还不能直接利用按钮上的字符作区分。

 

  苹果对UIKit中各个控件除了指定有大小、颜色等属性外,还有一个tag的属性。这个标记是专门给开发人员使用的,系统永远不会设置或修改它的值。如果我们在Interface Builder中设置了这个标记值,就可以通过它快速可靠地确定通过sender参数传递给操作方法的控件是哪一个了。

 

  回到CalculatorViewController.h上,对各种操作按钮定义一个常量,然后我们再到Interface Builder上给那些按钮设置相应的tag值。

 

 

#define clearBtn1
  …
  #define equalBtn8

 

ios科学计算器代码 iphone计算器代码_ios科学计算器代码_06

 

 

       这样,我们就可以把tag值用作switch变量,完整的buttonClicked定义如下:

 

 

- (IBAction)buttonClicked: (id)sender
  {
         UIButton *btn = (UIButton *)sender;
 
         int tag = btn.tag;
 
         NSString *currentStr = display.text;
 
         switch(tag) {
                case clearBtn:
                       display.text= @"0";
                       bBegin= YES;
                       operand= 0;
                       operator= @"=";
                       break;
                case dotBtn:
                {
                       BOOL notDot = ([display.text rangeOfString:@"."].location == NSNotFound);
                       if(notDot)
                       {
                              currentStr= [currentStr stringByAppendingString:@"."];
                              display.text= currentStr;
                       }
                }
                       break;
                case signBtn:
                {
                       if([display.textisEqualToString:@"0"] )
                       {
                              return;
                       }     
 
                       double number = [display.text doubleValue];
                       number= number*(-1);
                       display.text= [NSString stringWithFormat:@"%g",number];
 
                       if(bBegin)
                              operand= number;
                }
                       break;
                case plusBtn:
                case subBtn:
                case mulBtn:
                case divBtn:
                case equalBtn:
                       [self inputOperator:btn.titleLabel.text];
                       break;
                default:
                       [self inputNumber:btn.titleLabel.text];
                       break;
         }     
  }

 

  代码逻辑比较简单,在这里就不再展开详述了。注意在最后部分,点击+、-、*、/、=都会调用inputOperator方法来处理,这个方法的定义如下:

 

- (void)inputOperator: (NSString *)opt
{
       double currentNumber = [display.text doubleValue];
 
       if(bBegin)
              operator= opt;
       else
       {            
              if([operatorisEqualToString:@"="])
              {
                     operand= currentNumber;
              }elseif([operator isEqualToString:@"+"])
              {
                     operand+= currentNumber;
              }elseif([operator isEqualToString:@"-"])
              {
                     operand-= currentNumber;
              }elseif([operator isEqualToString:@"*"])
              {
                     operand*= currentNumber;
              }elseif([operator isEqualToString:@"/"])
              {
                     if(currentNumber!= 0)
                     {
                            operand/=  currentNumber;
                     }
                     else{
                            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil
                                                          message:@"除数不能为零!" 
                                                          delegate:nil
                                                          cancelButtonTitle:@"关闭"
                                                          otherButtonTitles:nil];
                            [alert show];
                            [alert release];
                            operator= @"=";
                     }
              }
 
              bBegin= YES;
              display.text= [NSString stringWithFormat:@"%g",operand];                  
              operator= opt;
       }     
}
 
       Default分支就是输入数字的情况(还记得我们没有为数字按钮设置tag值吧,默认情况下该值为0),我们用inputNumber来处理:
 
- (void)inputNumber: (NSString *)str
{
       if([display.textisEqualToString:@"0"] && [strisEqualToString:@"0"])
       {
              return;
       }
 
       if(bBegin)
       {
              display.text= str;
       }
       else
       {
              display.text= [display.text stringByAppendingString:str];
       }
       bBegin= NO;
}

 

  编译之后,实际运行效果:

ios科学计算器代码 iphone计算器代码_#define_07

 

 

程序小结:

 

       回顾在上一节中提出的需求,我们的程序都把功能实现了吗?iPhone开发计算器也很简单对不对?

 

       通过这个程序,我们至少学会了基于视图的应用程序开发的流程(定义输入口和操作、连接到Interface Builder、实现我们的程序逻辑等),掌握了Xcode、InterfaceBuilder和模拟器之间的配合开发。

 

  读者们如果觉得还不够过瘾,可以自行在此基础上添加程序的记忆功能,甚至完成科学计算器的其他部分。

 

----------------------------------------------------分隔线----------------------------------------------------------

参考资料/扩展阅读

1.《iPhone创意开发入门与实战》,XMobileApp 著,人民邮电出版社,2010。

2.《iPhone Human Interface Guidelines》,苹果公司官方文档。(在线中英对照版点击这里)