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是全英文的,有很多人會用起來別扭。以后也許會繼續有一些簡單的教程。大家有什么意見或者建議盡管告訴我啊,一起進步。