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:方法中获取的,然后把结果添加到显示中。