1.创建一个新项目,选择“View-based Application”。输入名字“Cal”,这时会有如下界面。
2.选择Resources->CalViewController.xib并双击,便打开了资源编辑对话框。
3.我们会看到几个窗口。其中有一个上面写着Library,这里面全是控件。如果没有显示的话,就在最上面的“TOOLS”里单击一下就出来了。还有一个标题为“View”,这个就是视图了,在这里面加上控件,运行时就可以显示出来了。还有一个标题为“Attributes”,这个很明显的是属性,关于某个控件的属性就在这里面设置。
4.我们这次主要用的是两个控件。如下图:
上面的是按钮,下面的是一个文本框。按钮是用来负责单击123那些的,文本框是用来显示的。
5.拖动控件到View的合适位置,具体怎么拖动是你自己的事,我的结果如下图:
这里也有一个小技巧,这里有很多按钮,一个一个拖动是很麻烦的,这时,拖动一个后,选中它,按住Option(alt)键,直接拖动就可以出现一个副本,弄好上面一排后,选中一排四个,再向下拖动,就可以一下出现4个。
6.下面我们给按钮添加文字。方法是,先选中文字,然后在属性窗口里,找到Title项,在里面写上名字,最后点一下回车键。如图:
把其他的都添加好,我的结果是这样的:
7.设置文本框的属性,按下图设置:
因为计算器默认会显示一个0。
8.我们要添加代码了。
(1)在CaleViewController.h里,修改代码成如下形式:
@interface CaleViewController : UIViewController {
UITextField* txtResult;//用来表示输出口的,和TextField类型一致
}
@property(nonatomic, retain) IBOutlet UITextField* txtResult;//表示这是一个输出口
-(IBAction)ButtonPressed:(id)sender;//这是一个事件的操作部分的声明
@end
(2)在CaleViewController.m文件里按如下修改:
#import "CaleViewController.h"
@implementation CaleViewController
@synthesize txtResult;//通知编译器为我们创建访问方法和修改方法
上面的是在文件最上面,然后添加函数:
-(IBAction)ButtonPressed:(id)sender{
}
只要在@end之前就行。这是一个空函数,现在我们还没有写到功能部分。
在- (void)dealloc {}函数里加上一句,当然应该在它原有的那句之前了,[txtResult release];
这是释放内存。因为IPHONE的机身内存有限,不可能像平时用电脑一样,所以一定要记得释放内存。而且由于都是指针操作,释放内存要注意,有时候就会释放错了,要多多理解指针。
9.下面要进行的是连接,只有把输入输出口连接起来,才能实现交互操作。所以,我们要把控件和表示控件的变量,操作的函数等连接起来。
具体操作如下:
连接UITextField* txtResult;和文本框控件,在控件操作程序下,按住键盘上的“CTRL”键,再单击并拖动,会出现一条蓝色的线,拖动到VIEW里的文本框控件上松开鼠标,会弹出小下拉菜单,里面就有一个txtResult,如果没有的话,检查你的定义和声明,看看类型是否一致等。再单击一下txtResult就可以了。这就连接上了。这时我们有了一个输出口,就是说以后txtResult变量就是文本框的内容。
连接按钮和操作。有两种方法,方法一:在按钮上单击右键,在对应的事件的右边圆圈里单击并拖动到上,松开就可以了。如图:
方法二:先单击按钮,然后在属性窗口里,找到如图所示:
单击ButtonPressed后面的那个小圆圈(有可能里面有黑点,没事的,正常现象),拖动到对应的按钮上松手,选择相应的事件就OK了。
最后说,我们选择的是Touch Up Inside事件,至于原因,参考《IPhone3开发基础教程》第38页。
我们把所有的按钮都添加上同一个事件,这样就使我们的接口减少了很多。
想试试都管用吗?很简单,在ButtonPressed函数里添加如下代码就可以了。
NSString* strInput = [sender titleForState:UIControlStateNormal];
txtResult.text=strInput;
它的功能是改变文本框的内容为按钮上的字。试试吧。
当然,做完这一切,千万不要忘了保存。
10.现在就是写计算器主程序的时候了,我们的数字不能太大,Double的才能支持到多少位啊,所以要考虑的问题很多。
现在要开始真正的编程了。
好吧,我们现在来添加一个成员变量,用来表示当前屏幕上显示的数字。double displayNum;并且在viewDidLoad事件中初始化为0.0。
然后我们来给按钮添加tag,数字上1就是1,然后我的列表是如下的,你自己要记住自己是怎么添加的。
0~9-----------0~9; 点------10; +-×/---------11~14; =---------15; 平方------16;正负--------17;CE--------18。
当然,这样写是我的个人习惯,您们可以把数字连接一个事件,加减连接一个,我就不在这里说了。
先说一下,这个是我的制作过程记录,以后会出现修改,这是很正常的,做程序肯定是会经常修改的。我把写错的地方也记录下来是为了让大家(尤其是初学者)来看清楚制作过程,制作过程永远不会一帆风顺。
添加一个成员函数,记住,要添加声明和定义两部分。
(double)NumPress:(int)Num;//我们用它来处理按下数字的操作
变量入口是按下的数字,返回值是目前这个数字是什么。
这个函数里先添加一句 displayNum = displayNum*10 + num;//修改显示的数字
貌似就结束了。但是这肯定是不正确的。
比如我们还要处理点和加减等操作。
我们把这个操作放到按钮的单击事件里。
代码如下:
-(IBAction)ButtonPressed:(id)sender{
//UIButton* btn = (UIButton*)sender;//用变量指向指令发送者
int num = [sender tag];//获取tag值
switch (num) {
case0:case1:case2:
case3:case4:case5:
case6:case7:case8:
case9://这部分是处理数字输入的
[selfNumPress: num];
break;
default:
break;
}
}
我们先来处理小数点被按下时。先添加一个成员变量,指示小数点是否被按下。BOOL IsDotPressed;并在viewDidLoad里将其初始化为NO。
添加函数,(void)DotPress{IsDotPressed = YES;}
这样的话,我们的数字按下事件就又要有变化了。
-(void)NumPress:(int)num{
if (IsDotPressed) {
++afterDotNum;//先让按下的小数点后的位数加1
displayNum = displayNum + pow((double)0.1,afterDotNum)*num;
}
else {
displayNum = displayNum*10 + num;//修改显示的数字
}
}
我们当然要让它能显示出来,否则也无法测试,不过,控件只能显示NSSTring*类型,所以要转换一下。
用以下函数,添加进去。
- (NSString *)changeFloat:(double)Right
{
NSString *stringFloat;
stringFloat = [NSStringstringWithFormat:@"%.10f",Right];
constchar *floatChars = [stringFloat UTF8String];
NSUInteger length = [stringFloat length];
int i;
for( i = length-1; i>=0; i--)
{
if(floatChars[i] == '0')
;
else
{
if(floatChars[i] == '.')
i--;
break;
}
}
NSString *returnString;
if(i == -1)
returnString = @"0";
else
returnString = [stringFloat substringToIndex:i+1];
return returnString;
}
然后我们就要调用了,在按钮单击事件里的switch的数字处理中,添加如下代码:
[txtResultsetText:[selfchangeFloat:displayNum]];
这样就可以调用了,不过,我们发现按下点后,点却并不出现,直到再按下一个数字时,点才会出现,这显然不是我们想要的。所以,要修改处理点按下的操作。
改成如下状态:
-(void)DotPress{
if(IsDotPressed == NO)
{
[txtResultsetText:[NSStringstringWithFormat:@"%@%@", [txtResulttext], @"."]];//这里是格式化字符串,在字符串后面添加个点
IsDotPressed = YES;
}
}
这样就OK了。
还有一点,就是数字长度问题,数字不能无限大,所以要添加一个判定条件,在数字按下的函数最前面添加以下代码:
//长度大于等于9位时,不再操作了
if ([txtResult.text length] >= 9 ) {
return;
}
下面是操作符号和等于的做法了,先说符号的。
先回忆一下计算器的工作流程,输入第一个数字,输入符号,输入第二个数,等于。这是一般的情况。我们先按一般情况来做。
添加两个函数,一个负责处理符号,一个负责等于。
-(void)OperPress:(int)oper{
WhichOperPressed = oper-10;
preInputNum = displayNum;
}
WhichOperPressed这个是int类型的成员变量,用来记录是哪个符号的,其中0-无,1-加,2-减,3-乘,4-除。
然后是等于的操作函数。
-(void)EquPress{
switch (WhichOperPressed) {
case1://加
displayNum += preInputNum;
break;
case2://减
displayNum = preInputNum-displayNum;
break;
case3://乘
displayNum *= preInputNum;
break;
case4://除
if (displayNum==0) {
[txtResultsetText:@"除数不能为0"];
return;
}
else {
displayNum = preInputNum/displayNum;
}
break;
default:
break;
}
[selfinit];
[txtResultsetText:[selfchangeFloat:displayNum]];
}
嗯,init也是一个函数,主要是清除工作,也可以说是初始化工作。代码如下:
-(void)init{
preInputNum = 0.0;
IsNumPressed=NO;
WhichOperPressed=0;
IsDotPressed=NO;
afterDotNum=0;
IsCaled=YES;
}
一般情况就是这样的,但是,我们有时会有这样的情况,输入数字,按了加号,但是发现按错了,于是按减号再输入第二个数字,再等于。这是一种,还有一种,我们输入第一个数字,按加,输入第二个数字,按加(此时应该显示的是前面两个数字的和),再输入第三个数字,等等。
所以有必要修改一下代码。
将操作符的代码做如下修改:
-(void)OperPress:(int)oper{
if (IsNumPressed) {
//计算结果
[selfEquPress];
}
WhichOperPressed = oper-10;
preInputNum = displayNum;
IsNumPressed=NO;
IsCaled=NO;
IsDotPressed=NO;
}
其中IsNumPressed是BOOL类型的成员变量,初始化为NO,用来表示是否有数字按下,这是处理这两种特殊情况的。
IsCaled是BOOL类型的成员变量,初始化为NO,这个的用处不在此处,而是要在NumPress函数里,修改一下代码:
-(void)NumPress:(int)num{
IsNumPressed = YES;
//如果有操作符号按下,则将显示的先归0
if (WhichOperPressed!=0 || IsCaled) {
displayNum = 0;
[txtResultsetText:[selfchangeFloat:displayNum]];
}……
下面的代码都一样,就不粘了,这里主要是为了在按了等于后,再次按数字,会使数字从0开始,否则按了等于后,再按数字就在数字后面继续添加数字了。
然后是平方的运算,按了平方后的做法,特别简单,就不用再添加成员函数了,就在btnPress的switch里添加就行了,添加如下代码:
case16://平方
displayNum*=displayNum;
[txtResultsetText:[selfchangeFloat:(displayNum)]];
[selfinit];
break;
然后该正负的按钮了。正负的出现很简单,在上面的后面再加一句:
case17:
displayNum = 0-displayNum;
[txtResultsetText:[selfchangeFloat:(displayNum)]];
break;
是不是很简单?不过,你可以试验一下,如果现在你按了3,再按正负,再按6,出现的不是-36而是-24,这是为什么呢?因为前面我们是加的-30+6当然是-24了。
所以,NumPress函数又要修改了。
。。。。。。
//长度大于等于9位时,不再操作了
if ([txtResult.textlength] >= 9 ) {
return;
}
//添加的是如下部分
if (displayNum<0) {//主要负责按了正负号后
num = 0-num;
}
/添加的是以上部分
if (IsDotPressed) {
++afterDotNum;//先让按下的小数点后的位数加1
displayNum = displayNum + pow((double)0.1,afterDotNum)*num;
}
…...
其他的部分相同,就省略了。
下面是CE按钮了,这个是清除用的,用我们的init就差不多了,在BtnPress里添加如下代码:
case18://CE
[selfinit];
displayNum=0;
[txtResultsetText:@"0"];
break;
现在,一个基本的计算器就完成了,我们还要测试一下,打开后,输入0.8,按+再按点,怎么了,是不是出现了“0.8.”呢?这显然有问题,修改吧,肯定是点处理的错,回想一下,点操作只是判断了一下以前有没有输入过点,而无论是符号的,还是等号的,都把其归为NO了,所以出现是很正常的,因此,我们修改成以下代码:
-(void)DotPress{
//如果有操作符号按下,则将显示的先归0
if (WhichOperPressed!=0 || IsCaled) {
displayNum = 0;
[txtResultsetText:[selfchangeFloat:displayNum]];
}
if(IsDotPressed == NO)
{
[txtResultsetText:[NSStringstringWithFormat:@"%@%@", [txtResulttext], @"."]];
IsDotPressed = YES;
}
IsNumPressed=YES;
IsCaled=NO;
}
因为如果有操作符按下后,按点时就相当于按了0和点,所以这样就没问题了。再试试除个0,怎么样,提示出现了吧,再按任意的数字键呢?怎么?没问题?多点几个试试 ,问题有了没?就是只能显示一位数了。这可如何是好呢?在EquPress函数里,找到以下地方:
case4://除
if (displayNum==0) {
[txtResultsetText:@"除数不能为0"];
[selfinit];//在这添加一句就OK了
return;
}
我们只要在上面注释的地方添加一句就OK了。大家去想想原因吧。到此,一个简单的计算器就做好了,基本功能全都有了。像界面什么的,自己去动脑子吧。
写在最后:这个功能很简单,目的只是为了将初学者引进门。因为乍一遇到XCODE这样的编译器,有很多人会很不习惯,而且会感觉无从下手。其实IPHONE编程还是很简单的,大家稍微用点心,练习一下,手熟点就没有任何问题的。关键还有就是XCODE是全英文的,有很多人会用起来别扭。以后也许会继续有一些简单的教程。大家有什么意见或者建议尽管告诉我啊,一起进步。