21.3.2 定义视图控制器
现在让我们编写视图控制器Fraction_CalculatorViewController的代码。我们将从接口文件开始,如代码清单21-2所示。
代码清单21-2 Fraction_CalculatorViewController.h接口文件
import<UIKit/UIKit.h>
import“Calculator.h”
@interface Fraction_CalculatorViewController:UIViewController{
UILabel*display;
char op;
int currentNumber;
NSMutableString*displayString;
BOOL firstOperand, isNumerator;
Calculator*myCalculator;
}
@property(nonatomic, retain)IBOutlet UILabel*display;
@property(nonatomic, retain)NSMutableString*displayString;
-(void)processDigit:(int)digit;
-(void)processOp:(char)theop;
-(void)storeFracPart;
//Numeric keys
-(IBAction)clickDigit:(id)sender;
//Arithmetic Operation keys
-(IBAction)clickPlus:(id)sender;
-(IBAction)clickMinus:(id)sender;
-(IBAction)clickMultiply:(id)sender;
-(IBAction)clickDivide:(id)sender;
//Misc.Keys
-(IBAction)clickOver:(id)sender;
-(IBAction)clickEquals:(id)sender;
-(IBAction)clickClear:(id)sender;
@end
有一些内务管理变量分别用于构造分数(currentNumber、firstOperand和isNumerator)和构造显示字符串(displayString)。还有一个Calculator对象(myCalculator)用于执行两个分数间的实际计算。我们将把一个名为clickDigit:的方法关联到处理按下数字键0~9的操作上。最后,我们定义了一些方法,用于保存要执行的运算(clickPlus:、clickMinus、clickMultiply:、clickDivide:):当按下=键时,执行实际计算(clickEquals:),清除当前运算(clickClear:);当按下Over键时,分离分子与分母(clickOver:)。还有一些方法(processDigit:、processOp:和storeFracPart)用于帮助处理上面提到过的一些杂事。
代码清单21-2显示了这个控制器类的实现文件。
代码清单21-2 Fraction_CalculatorViewController.h实现文件
import“Fraction_CalculatorViewController.h”
@implementation Fraction_CalculatorViewController
@synthesize display, displayString;
-(void)viewDidLoad{
//Override point for customization after application launch
firstOperand=YES;
isNumerator=YES;
self.displayString=[NSMutableString stringWithCapacity:40];
myCalculator=[[Calculator alloc]init];
}
-(void)processDigit:(int)digit
{
currentNumber=currentNumber*10+digit;
[displayString appendString:[NSString stringWithFormat:@“i”,digit]];
[display setText:displayString];
}
-(IBAction)clickDigit:(id)sender
{
int digit=[sender tag];
[self processDigit:digit];
}
-(void)processOp:(char)theOp
{
NSString*opStr;
op=theOp;
switch(theOp){
case‘+’:
opStr=@;
break;
case‘-’:
opStr=@;
break;
case‘*’:
opStr=@;
break;
case‘/’:
opStr=@;
break;
}
[self storeFracPart];
firstOperand=NO;
isNumerator=YES;
[displayString appendString:opStr];
[display setText:displayString];
}
-(void)storeFracPart
{
if(firstOperand){
if(isNumerator){
myCalculator.operand1.numerator=currentNumber;
myCalculator.operand1.denominator=1;//e.g.3*4/5=
}
else
myCalculator.operand1.denominator=currentNumber;
}
else if(isNumerator){
myCalculator.operand2.numerator=currentNumber;
myCalculator.operand2.denominator=1;//e.g.3/2*4=
}
else{
myCalculator.operand2.denominator=currentNumber;
firstOperand=YES;
}
currentNumber=0;
}
-(IBAction)clickOver:(id)sender
{
[self storeFracPart];
isNumerator=NO;
[displayString appendString:@];
[display setText:displayString];
}
//Arithmetic Operation keys
-(IBAction)clickPlus:(id)sender
{
[self processOp:‘+’];
}
-(IBAction)clickMinus:(id)sender
{
[self processOp:‘-’];
}
-(IBAction)clickMultiply:(id)sender
{
[self processOp:‘*’];
}
-(IBAction)clickDivide:(id)sender
{
[self processOp:‘/’];
}
//Misc.Keys
-(IBAction)clickEquals:(id)sender
{
[self storeFracPart];
[myCalculator performOperation:op];
[displayString appendString:@];
[displayString appendString:[myCalculator.accumulator convertToString]];
[display setText:displayString];
currentNumber=0;
isNumerator=YES;
firstOperand=YES;
[displayString setString:@“];
}
-(IBAction)clickClear:(id)sender
{
isNumerator=YES;
firstOperand=YES;
currentNumber=0;
[myCalculator clear];
[displayString setString:@“];
[display setText:displayString];
}
-(void)dealloc{
[myCalculator release];
[super dealloc];
}
@end
和前一个应用程序一样,计算器窗口仍然包含一个标签,我们仍然称之为display。当用户逐位地输入一个数字时,我们需要同步构造这个数字。变量current_Number保存了这个输入中的数字,而BOOL变量firstOperand和isNumerator分别用于跟踪输入的是第一个还是第二个操作数,以及用户当前输入的是该操作数的分子还是分母。
在计算器上按下一个数字按钮时,我们会将它组装起来,这样可以将一些识别信息传递给clickDigit:方法,从而识别出按下的是哪个数字按钮。这是通过将每个数字按钮的tag属性(使用Interface Builder的Inspector)设为一个唯一值来实现的。在这个例子中,我们把tag设为了对应的数字。因此标为0的按钮的tag将被设为0,而标为1的按钮的tag将被设为1,依此类推。接下来,把tag消息发送给clickDigti:方法的sender参数,就可以获得按钮tag的值。这是在clickDigit:方法中完成的,如下所示:
-(IBAction)clickDigit:(id)sender
{
int digit=[sender tag];
[self processDigit:digit];
}
代码清单21-2中的按钮比第一个应用程序中要多得多。视图控制器实现文件中的复杂性大部分来自于构造和显示分数。如前所述,按下数字按钮0~9时,就会执行操作方法clickDigit:。该方法会调用processDigit:方法并将相应的数字附加到变量currentNumber中正在构造的数字末尾。该方法还会把数字添加给变量displayString中保存的当前显示字符串,并更新显示内容:
-(void)processDigit:(int)digit
{
currentNumber=currentNumber*10+digit;
[displayString appendString:[NSString stringWithFormat:@“i”,digit]];
[display setText:displayString];
}
按下=键时,就会调用clickEquals:方法执行运算。计算器将执行两个分数之间的运算,并将结果保存在其累加器中。这个累加器的值是在clickEquals:方法中获取的,然后把结果添加到显示中。