簡單的iOS開發執行個體,簡單iOS開發執行個體
項目需求
寫一個iPhone應用程式,要求可以輸入名字,點擊按鈕後,會顯示一段文字向輸入的名字打招呼,例如輸入“寶玉”,顯示“你好,寶玉!”
需求分析
這是一個很簡單的應用程式,包含一個文本輸入框,一個文本顯示框,一個按鈕。輸入名字到文本輸入框,再點擊按鈕,這時文本顯示框的文字就會變成“你 好,<名字>!”。但是要注意,如果使用者輸入為空白,要有警告提示使用者重新輸入;如果使用者輸入文字太長,超過16個字元,要自動截斷。
產品設計
根據項目需求,畫出相應的產品原型圖:
初始狀態
初始時,文本輸入框為空白,但是顯示浮水印,提醒使用者可以輸入姓名。文本顯示框文字為空白。
輸入名字並點擊按鈕後
輸入名字,並點擊按鈕後,螢幕中間顯示文字:“您好,<名字>!”。
沒有輸入名字的警告提示
如果沒有輸入名字,點擊按鈕後彈出警告視窗,提醒使用者輸入名字。
系統分析
這是一個非常簡單的應用程式,實現思路不不算複雜:
- 一個文本輸入框,用來輸入文字,需要限制最大字元長度為16個字元,輸入框沒有內容時,顯示浮水印文字。UITextField控制項正好可以滿足需求。
- 一個文本顯示框,用來顯示最終產生的文字。使用UILabel控制項即可滿足需求。
- 一個按鈕,點擊後,擷取文本輸入框文字內容,產生“你好,<名字>!”文字,並顯示在文本顯示框中。如果點擊時文本輸入框文字為空白,彈出警告提示框。
同時,這個應用程式在開發過程中,需要應用到iPhone開發中一些常用的設計模式:
- 委託(Delegate)
- 模型 視圖 控制器(MVC)
- 目標 - 動作(Target-Action)
委託(Delegate)
委託模式是一個對象周期性地向被指定為其委託的另一個對象發送訊息,向其請求輸入或者通知某件事情正在發生。該模式可替換類繼承來對可複用對象的功能進行擴充。
在本項目中,應用程式物件會向其委託發送訊息,通知它主要的啟動常式已經完成並且定製的配置可開始執行。為了建立並管理檢視,委託會建立一個控制器執行個體。另外,當使用者點擊Return按鍵後,文字欄位也會通知它的委託(即所建立的控制器對象)
委託方法通常會集中在一起形成一份協議。 一份協議基本上就是一個方法的列表。如果一個類遵循某個協議,則它要保證實現協議所要求的方法(有些方法可選擇實現與否)。委託協議規定了一個對象可以發 送給委託的所有訊息。例如常見的有:UITextFieldDelegate, UIApplicationDelegate, UIScrollViewDelegate, UITableViewDelegate, UIWebViewDelegate。
模型 視圖 控制器(MVC)
MVC模式將應用程式中的對象設定為三種角色:模型角色(Model)、視圖角色(View)和控制器角色(Controller)。
模型對象(Model)表示資料。例如,在iPhone內建的通訊錄應用中,連絡人是模型對象,在一個繪畫應用中,圓形、矩形是模型對象。
本項目的應用程式用到的資料非常簡單——字串,並且該字串只有在按鈕點擊的方法中用到。其實換一種角度來說,字串也是一種最簡單的模型對象,在其他的應用程式中,模型對象將會更加複雜,並且模型對象在程式中無處不在,可以在多個地方進行訪問。
視圖對象(View)負責顯示資料,比如UILabel可以顯示文本、UIImageView可以顯示圖片,也會支援使用者對資料的編輯操作,例如UITextField可以支援使用者輸入。
在我們接下來要建立的項目中,需要一個主視圖來包含其它幾個視圖——首先是一個文本輸入框,它用於捕獲使用者輸入資訊;然後是一個文本顯示框,它用於顯示文本,而常值內容則是基於使用者的輸入;另外還需要一個按鍵,讓使用者可以點擊它,點擊後通知文字欄位更新。
控制器對象(Controller)介於模型和視圖之間。
在我們接下來要建立的項目中,當使用者點擊按鈕後,觸發更新操作,控制器對象將會從文本輸入框中擷取輸入的文字內容,並把文字存放在一個字串中,然後再把文本顯示框的內容更新成格式化好的內容。
結合MVC模式,對於本項目的主要流程,整個:
目標 - 動作(Target - Action)
目標-動作機制,允許一個控制項對象(例如按鍵或滑動條) 向另外一個對象發送一條訊息(即動作),以之作為對某個使用者事件(例如一個點擊事件)的響應。接收到訊息的對象則可以對訊息進行響應,並針對業務要求做出處理。
在本項目中,當點擊按鈕時,它會通知控制器去擷取文本輸入框內容,並根據輸入內容更新文本顯示框。
開發建立項目
我們將開始使用Xcode來建立項目,啟動Xcode(預設情況下,Xcode位於 /Developer/Applications 裡面),然後選擇File > New > New Project,這樣就可以建立一個新的工程。應該可以看到一個新的視窗,如所示:
選中 Window-Based Application 並點擊 Next 按鈕,輸入Product Name(項目名):SayHello,在Company Identifier那,可以輸入公司名唯一標識。
點擊Next,選擇項目儲存位置,最後點擊Create按鈕。
完成上述步驟後,將看到如下的新項目視窗:
在進行下一步工作之前,可以先編譯運行一下程式,這樣就可以通過模擬器看到程式運行後的樣子。在Xcode的菜單中選擇 Product > Run 或者點擊左上方工具列上的 Run 按鈕,iPhone模擬器應該會自動啟動。當應用程式啟動後,可以看到一個白色螢幕。
應用程式啟動過程解析
通過Xcode的模板建立項目時,模板已經協助設定好了應用程式基底本程式環境,它會協助建立一個應用程式物件,將應用程式和視窗串連起來,建立一個運行環境。整個啟動過程從UIApplicationMain函數開始,如所示:
main.m檔案中的main函數會調用UIApplicationMain函數:
int retVal = UIApplicationMain(argc, argv, nil, nil);
該函數將會建立一個UIApplicaion類的執行個體。同時它會搜尋應用程式的Info.plist屬性列表檔案。 Info.plist檔案是一部字典,它主要包含諸如應用程式名稱、表徵圖這樣的資訊,它也包含應用程式物件應該載入的nib 檔(雖然該檔案的副檔名為“xib”,但是我們習慣稱之為“nib 檔”)的名稱。Nib檔案主要有使用者介面的資訊。本項目的Info.plist檔案具有下面的內容:
術語: 雖然Interface Builder文檔的副檔名可能是“.xib” ,但曆史上,其副檔名是“.nib”(“NextStep Interface Builder”的首字母縮寫),因此人們就俗稱其為“Nib檔案”。
這表明應用程式啟動時將會載入MainWindow nib檔案。在Xcode中可以單擊MainWindow.xib進行查看(注意在Xcode4中已經不需要通過Interface Builder來開啟nib檔案,可以直接在Xcode對nib檔案進行查看和編輯):
MainWindow Nib文檔包含4個對象:
- File's Owner,檔案擁有者代理對象,在這裡MainWindow的擁有者對象時UIApplication執行個體
- First Responder,第一響應者代理對象,在本項目中,沒有使用到
- Say Hello App Delegate,SayHelloAppDelegate的執行個體,也就是應用程式的委託
- Window,一個視窗對象。它預設是白色背景,程式啟動時看到的就是它
應用程式物件在完成啟動後,會向委託發送applicationDidFinishLaunching:訊息,通知程式已經啟動成功了,這樣我們可以在收到這個訊息後根據需要進行一些操作。是一個簡化的iPhone應用程式生命週期圖,簡要展示了發生在應用程式啟動到退出的過程。
這樣,我們基本瞭解了如何建立一個項目,以及一個應用程式的啟動過程,接下來,我們需要建立一個視圖控制器(UIViewController)執行個體,用來實現項目功能。
添加視圖控制器(UIViewController)添加視圖控制器檔案
在iPhone應用程式中,視圖控制器(UIViewController)起著核心作用。顧名思義,視圖控制器負責管理控制視圖。在iPhone上,它們也協助進行導航和記憶體管理。
選中Xcode專案管理器裡的項目(即SayHello項目,位於Groups and Files列表的頂部)或者選中SayHello檔案夾——新檔案在添加時會被加入到當前選擇的位置。 選中後,在Xcode菜單中選擇 File > New > New File,也可以在選中的檔案夾上面點右鍵,選擇 New File。
在New File視窗中,請選擇Cocoa Touch,然後選擇UIViewController subclass。
點擊 Next 按鈕,在Options視窗,請勾選 “With XIB for user interface”複選框。選中 “With XIB for user interface”後,Xcode在建立視圖控制器的同時,會為其建立一份nib檔案,並將該檔案添加到項目中。
點擊Next按鈕,在其後出現的儲存檔案視窗中,為檔案起個名字,例如RootTimelineViewController,並選擇檔案儲存體的位置,如下所示:
點擊 Save,檔案會被添加到項目中。接下來,我們將建立控制器類的執行個體。
建立視圖控制器執行個體
現在,我們有了視圖控制器的類和nib檔案,但要在應用程式代理程式中使用它,還必須建立類的執行個體,並且將執行個體儲存在變數中,以便操作它。
在應用程式委託類的標頭檔(即SayHelloAppDelegate.h)中執行下述操作:
在一個類中訪問另一個類,首先需要引用被訪問類的標頭檔。所以我們先在應用程式委託標頭檔(SayHelloAppDelegate.h)的介面聲明前面-即SayHelloAppDelegate聲明前面引用視圖控制器(RootViewController)的標頭檔:
#import "RootViewController.h"
然後在標頭檔大括弧之間添加下面的代碼,這是為了嚮應用程式委託添加一個執行個體變數:
RootViewController *viewController;
在大括弧之後 @end之前添加下面的屬性聲明:
@property (nonatomic, retain) RootViewController *viewController;
在標頭檔中添加完相應變數和屬性申明後,需要在對應的實現檔案中,合成屬性的存取方法,在dealloc方法中釋放視圖控制器的執行個體。
在應用程式委託類的實現檔案(即SayHelloAppDelegate.m)中執行下述操作:
在類的 @implementation代碼塊中通知編譯器為視圖控制器合成存取方法:
@synthesize viewController;
在dealloc方法起始處釋放視圖控制器:
[viewController release];
我們已經把視圖控制器屬性添加到應用程式的委託,現在需要實際建立一個視圖控制器執行個體,並將其設定為屬性的值。
在應用程式委託類實現檔案(即SayHelloWorldAppDelegate.m檔案)中的applicationDidFinishLaunching: 方法開頭添加如下代碼,這些代碼用於建立一個RootViewController執行個體:
RootViewController *controller = [[RootViewController alloc]initWithNibName:@"RootViewController" bundle:nil];
self.viewController = controller;
[controller release];
這段代碼的作用如下:
- 建立RootViewController這個視圖控制器的執行個體。使用alloc方法建立一個視圖控制器,然後用initWithNibName:bundle:方法對其進行初始化。init方法先指定控制器應載入的nib檔案,然後指定在哪個程式包中可找到該檔案。程式包是檔案系統某個位置的抽象,該位置存放了應用程式將會用到的代碼和資源。
- 使用屬性的存取方法,將建立好的視圖控制器執行個體設定為viewController屬性變數的值
- 根據記憶體管理規則釋放視圖控制器
視圖控制器用來配置和管理在應用程式中看到的視圖,每一個視圖也對應有一個視圖控制器來管理。表單(window)有一個根視圖控制器——這個視圖控制器負責配置當表單顯示時最先顯示的視圖。要讓你的視圖控制器的內容顯示在表單中,需要去設定表單的根視圖控制器為你的視圖控制器。
所以我們的項目中,在上面建立視圖控制器執行個體代碼後面再添加一行代碼,來設定表單的根視圖控制器為我們新添加的視圖控制器:
self.window.rootViewController = controller;
最後一行來自於Xcode提供的模板自動產生的程式碼:
[self.window makeKeyAndVisible];
這行代碼會讓包含了視圖控制器視圖的Window視窗顯示在螢幕上。
本章完整代碼,SayHelloAppDelegate.h檔案:
#import <UIKit/UIKit.h>
#import "RootViewController.h"
@interface SayHelloAppDelegate : NSObject <UIApplicationDelegate> {
RootViewController *viewController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) RootViewController *viewController;
@end
SayHelloAppDelegate.m檔案:
#import "SayHelloAppDelegate.h"
@implementation SayHelloAppDelegate
@synthesize window=_window;
@synthesize viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RootViewController *controller = [[RootViewController alloc]initWithNibName:@"RootViewController" bundle:nil];
self.viewController = controller;
[controller release];
self.window.rootViewController = controller;
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
[_window release];
[viewController release];
[super dealloc];
}
@end
測試回合
在Xcode的菜單中選擇 Product > Run 或者點擊左上方工具列上的 Run 按鈕,iPhone模擬器應該會自動啟動。當應用程式啟動後,還是看到一個白色螢幕,不過第一次看到的白色螢幕,是應用程式代理程式中的Window,而這次看到的白色螢幕,是視圖控制器RootViewController中的視圖。
下一步,我們將開始對介面進行編輯。
編輯Nib檔案
在iPhone開發中,一般都會用NIB檔案來來負責介面顯示,也就是MVC模型裡面的視圖對象,而NIB檔案只包含使用者介面元素,不包含任何源碼,那麼怎麼讓視圖對象和視圖控制器關聯起來呢?這就需要用到兩個非常重要的概念:插座變數(outlet)和檔案擁有者代理對象(File's Owner)。
視圖控制器的視圖和Nib檔案
視圖控制器主要的職責就是配置和管理應用程式中所有的視圖,一般來說,視圖控制器的視圖是放在一個Nib檔案中,當然也可以不需要Nib檔案,通過程式建立視圖,典型的如UITableViewController這樣的視圖控制器,就可以不需要Nib檔案。在建立視圖控制器執行個體時,其中一個主要的建構函式 initWithNibName:bundle: 的第一個參數就是視圖控制器對應的Nib檔案的名字。視圖控制器在其 loadView 方法中載入它的Nib檔案。如果是使用 initWithNibName:bundle: 建構函式產生的執行個體,並且你想在視圖載入完成後進行額外的設定,只要重寫視圖控制器的 viewDidLoad 方法就好了。
在Xcode中點擊開啟視圖控制器的Nib檔案(即RootViewController.xib檔案),在Xcode中即可直接查看和編輯。檔案包含三個對象,檔案擁有者代理(File's Owner),第一響應者代理(First Responder)以及一個視圖(View)。視圖(View)是視圖控制器的主視圖,在主視圖中還可以添加若干子視圖。檔案擁有者代理(File's Owner)代表Nib檔案對應的視圖控制器類。理解檔案所有者代理的角色,以及如何建立檔案所有者和Nib檔案中介面元素之間的串連,是非常重要的。
小貼士: 在Xcode中編輯Nib檔案時,可以通過點擊右上方工具列按鈕 顯示隱藏相應面板,方便對介面編輯和屬性設定。 檔案擁有者(File's Owner)
在一個Nib檔案中,檔案擁有者對象是其中最重要的對象之一,因為正是通過它,來建立起應用程式代碼和Nib介面檔案中對象之間的串連,具體來說,它就是對應Nib檔案的視圖控制器對象。以本項目為例,RootViewController.xib這個Nib檔案的檔案擁有者對象就是RootViewController類的執行個體。
一般來說,在使用模板同時建立UIViewController檔案和對應的Nib檔案時,它預設會設定Nib檔案對應的檔案擁有者為建立的UIViewController類。如果要修改或者設定Nib檔案對應的檔案擁有者,可以使用 Identity Inspector 面板進行設定。
如所示, 本項目的RootViewController.xib檔案對應的檔案所有者,在Identity Inspector 面板中,Custom Class部分的Class項,可以看到對應的值是RootViewController,這表示檔案擁有者就是RootViewController類的執行個體,就可以在Xcode中訪問檔案擁有者類裡面標誌為IBOutlet的屬性和IBAction的方法,和Nib檔案中的介面元素建立關聯。
視圖插座變數
在Xcode中,使用 Inspector 面板,或者在串連面板,可以查看、建立、刪除對象之間的串連。要查看視圖控制器的串連,可以通過以下步驟:
在上面第三步,右側面板顯示的串連面板和右鍵點擊File's Owner彈出的半透明串連面板,顯示的資訊和作用都是一樣的,可以根據個人習慣靈活使用。到目前為止唯一的串連是視圖控制器的 view 插座變數。一個插座變數就對應視圖控制器類的一個屬性(有時候也可以是一個執行個體變數),只不過這個屬性和nib檔案中的某個介面元素串連在一起。此處的view的串連,表明當nib檔案 RootViewController.xib 被載入,並且UIView的執行個體解檔之後,視圖控制器的view執行個體變數會被設定為指向nib檔案中的視圖。
中間測試
在項目開發中,尤其在對開發工具和語言不熟悉的時候,需要經常性的對新增的功能進行測試,以確保當前功能運行是正常的。比如我們新增了RootViewController這個自訂視圖控制器,需要去測試一下它是不是已經成功添加。要測試檢視控制器工作正常,簡單的辦法修改視圖控制器的視圖的背景色,例如修改為粉紅色背景,然後重新運行,看看是不是介面變成了紅色背景。
要設定視圖控制器的視圖的背景色,步驟如下:
正常情況下,編譯應該不會出現任何錯誤,運行後會彈出模擬器,結果如所示:
確認沒有問題後,再將應用的背景色還原。還原的話,將視圖的背景色設定為白色就好了。
配置視圖
Xcode提供了一套物件程式庫,可以直接添加到Nib檔案中。其中一部分示介面元素,例如按鈕和文本輸入框;其他一部分是控制器對象,例如視圖控制器。我們當前項目的nib檔案已經包含了視圖,現在只要添加按鈕和文本輸入框就好了。從物件程式庫中將使用者介面元素拖動到視圖中,基本步驟如下:
如果我們想讓使用者在輸入時有一些更好的體驗,比如使用者輸入英文名時,預設會首字母大寫;比如鍵盤會顯示完成(Done)按鍵,點擊後完成輸入隱藏鍵盤。要支援這樣的輸入細節,通過設定文字框屬性就可以完成:
- 在Capitalization下拉式清單,選擇Words,以支援首字母大寫
- 在Return Key下拉式清單,選擇Done,以支援鍵盤上顯示完成(Done)按鍵
儲存檔案後,編譯運行程式,可以看到啟動並執行介面效果和我們在Xcode中擺放的效果是一樣的。點擊按鈕,按鈕會高亮,在文本輸入框中點擊,會彈出輸入鍵盤,鍵盤裡可以看到完成(Done)按鈕。但是還不能根據輸入的內容去顯示文字,還不能隱藏鍵盤,因為目前我們還僅僅完成了視圖部分的工作,還需要讓視圖中的對象和視圖控制器的對象之間建立串連,並添加相應的邏輯,才能實現。
實現視圖控制器
實現視圖控制器需要完成以下幾件事:
建立串連
從業務角度來看,我們需要和介面的幾個元素建立關聯:
在Xcode4之前,Interface Builder和Xcode是分開的,一般是先在Xcode中定義好插座變數和動作方法,然後再在InterfaceBuilder中去建立介面元素和視圖控制器之間的串連,到Xcode4之後,Interface Builder和Xcode已經統一合并在了一起,所以這部分也有一些變化,Xcode4讓這部分工作變的更加容易一些,可以直接從視圖編輯介面拖動串連到代碼檔案。
在我們正在開發的SayHello項目中,現在我們需要添加一個動作方法到視圖控制器,當介面上的按鈕被點擊時,它會發送一個sayHello:訊息到視圖控制器,所以接下來要為按鈕建立一個sayHello:動作方法:
通過上面的為按鈕添加動作的操作,完成了兩件事
接下來要建立文本輸入框和文字標籤之間的串連:
通過上面的為文本輸入框添加插座變數的操作,完成了兩件事
按照上面建立文本輸入框插座變數相同的方法,再建立用來顯示問候語的文字標籤的插座變數,並且將插座變數命名為 greetingLabel,類型為 UILabel。
實現邏輯代碼
點擊視圖中的按鈕,它會向視圖控制器發送 sayHello: 訊息,之後,視圖控制器會取得文本輸入框文字內容,根據內容來更新用來顯示問候語的文字標籤的內容。以下是RootViewController.m檔案中 sayHello: 方法代碼的實現:
- (IBAction)sayHello:(id)sender {
// 擷取文本輸入框內容,並儲存到變數中
NSString *nameString = nameTextField.text;
// 檢查輸入的名字是否為空白,如果為空白,彈出提示資訊
if (nameString.length == 0) {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"名字不可為空" message:@"請輸入名字後,重新點擊按鈕。" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
[alertView show];
[alertView release];
greetingLabel.text = @"";
return;
}
// 檢查名字是不是超過16個字元,超過16個字元自動截斷
if (nameString.length > 16) {
nameString = [nameString substringToIndex:16];
}
// 根據輸入的名字,產生問候語
NSString *greeting = [NSString stringWithFormat:@"你好,%@!", nameString];
// 顯示問候語
greetingLabel.text = greeting;
}
對於這個方法有幾點補充說明:
- UIAlertView是專門用來顯示訊息提示對話方塊
- stringWithFormat:方法符串按照格式化字串所指定的格式建立一個新字串。%@表明此處應該使用一個字串對象來代替。
隱藏鍵盤
編譯並運行應用程式。在文字框中輸入“Jim”,點擊按鍵後,標籤顯示“你好, Jim!” 。但是選擇文字欄位進行輸入,您會發現您沒有辦法表示已完成輸入,也沒有辦法消除鍵盤。在iPhone應用程式中,當一個允許文本輸入的元素變成第一響應者時,鍵盤就會自動顯示出來,而當該元素不再處於第一響應者狀態,鍵盤就會消失。我們不能直接向鍵盤發送訊息,但是可以切換文本輸入元素的第一響應者狀態,利用該操作的附加效果來顯示或消除鍵盤。在應用程式中,當使用者點擊文字欄位時,該控制項就會變成第一響應者,因此鍵盤就會顯示出來。而當使用者點擊鍵盤中的Done按鍵時,希望鍵盤消失。
UITextFieldDelegate協議包含一個textFieldShouldReturn:方法,一旦使用者點擊Return按鍵,文字欄位就會調用該方法(和按鍵的標題無關)。但將視圖控制器設定成文本輸入框(UITextField)的委託(Delegate),才可以實現該方法,在方法中向文字欄位發送resignFirstResponder訊息,這個訊息的附加效果會讓鍵盤消失。
通過以下步驟設定文本輸入框的委託(delegate)串連:
接下來,來實現將RootViewController作為文本輸入框nameTextField的委託(delegate)
至此我們已經開發完成了整個應用程式。接下來將對它進行測試。
測試
這個應用程式相對簡單,我們設計幾個測試情境:
針對這個測試情境,逐一做一下功能的測試,看起來結果和我們預期的完全一樣。
小結通過這樣一個簡單的項目,瞭解以下知識點:
- iOS開發常用的一些設計模式
- iPhone程式的啟動過程
- 視圖控制器和Nib檔案如何建立串連
這些知識對於iPhone開發和iOS開發來說,都是會經常用到的知識。
學android開發簡單還是ios開發簡單?
android是需要有java基礎,ios需要有一定的C語言基礎(使用Objective-C)。
但就開發過程來說,ios的開發比較簡單,他的很多方法是通過連線實現的,省去了很多的代碼。
我想開發ios簡單的遊戲
個人開發人員在蘋果註冊後腰支付600多人民幣一年的SDK使用費用
公司級的SDK每年要幾千甚至幾萬人民幣,但是其實都不貴
然後下載開發環境到自己電腦上開發。