終于到了真正接觸ios應用程式的時刻了,之前我們花了很多時間去讨論c語言、objc等知識,對于很多朋友而言開發ios第一天就想直接看到成果,看到可以運作的ios程式。但是這裡我想強調一下,前面的知識是你日後開發ios的基礎,沒有那些知識你開發ios會很痛苦,現在很多開發人員做開發都是一知半解,程式品質确實令人擔憂,是以還是希望大家能夠熟練掌握前面的内容,開發過程中多思考,徹底了解程式運作的原理、機制。好了言歸正傳,不管怎麼樣正式進入ios開發還是令人興奮的,今天的内容雖然說是開發預覽,其實還是有大量内容要說的:
<a href="http://www.cnblogs.com/kenshincui/p/3890880.html#firstios">第一個ios程式</a>
<a href="http://www.cnblogs.com/kenshincui/p/3890880.html#runprocess">ios程式運作過程</a>
<a href="http://www.cnblogs.com/kenshincui/p/3890880.html#filestructure">檔案結構</a>
<a href="http://www.cnblogs.com/kenshincui/p/3890880.html#storyboard">storyboard</a>
<a href="http://www.cnblogs.com/kenshincui/p/3890880.html#purecode">純代碼實作ios開發</a>
<a href="http://www.cnblogs.com/kenshincui/p/3890880.html#additional">補充知識點</a>
首先打開xcode—create a new xcode project—single view application--輸入項目名稱,同時選擇使用objective-c語言,裝置選擇iphone--接下來系統預設生成一個ios項目模闆。項目目錄結構如下:

此時什麼也不用做,直接運作看一下(注意這裡已經切換模拟器為iphone5),沒錯我們看到了一個ios應用程式:
在幾乎所有的程式開發中程式一般都是從main函數開始運作的,那麼ios程式也不例外,在上圖中我們可以看到xcode為我們生成了一個main.m檔案:
這個預設的ios程式就是從main函數開始執行的,但是在main函數中我們其實隻能看到一個方法,這個方法内部是一個消息循環(相當于一個死循環),是以運作到這個方法uiapplicationmain之後程式不會自動退出,而隻有當使用者手動關閉程式這個循環才結束。這個方法有四個參數:
第一個參數和第二個參數其實就是main函數的參數,分别代表:參數個數、參數内容;
第三個參數代表uiapplication類(或子類)字元串,這個參數預設為nil則代表預設為uiapplication類,使用者可以自定義一個類繼承于這個類;如果為nil則等價于nsstringfromclass([uiapplication class]),大家可以自己試驗,效果完全一樣;uiapplication是單例模式,一個應用程式隻有一個uiapplication對象或子對象;
第四個參數是uiapplication的代理類字元串,預設生成的是appdelegate類,這個類主要用于監聽整個應用程式生命周期的各個事件(其實類似于之前我們文章中提到的事件監聽代理),當uiapplication運作過程中引發了某個事件之後會調用代理中對應的方法;
小技巧: 其實在xcode中如果要看一些系統方法的解釋或者參數說明,可以直接滑鼠放到這個方法上,在xcode右側面闆中就會給出幫助提示,如下圖當我們放到uiapplicationmain上之後:![]()
iOS開發系列--IOS程式開發概覽概覽第一個iOS程式程式的運作過程檔案結構Storyboard純代碼實作iOS開發補充知識點
也就是說當執行uiapplicationmain方法後這個方法會根據第三個參數建立對應的uiapplication對象,這個對象會根據第四個參數appdelegate建立并指定此對象為uiapplication的代理;同時uiapplication會開啟一個消息循環不斷監聽應用程式的各個活動,當應用程式生命周期發生改變uiapplication就會調用代理對應的方法。
既然應用程式uiapplication是通過代理和外部互動的,那麼我們就有必要清楚appdelegate的操作細節,下面是uiapplication詳細的代碼:
appdelegate.h
appdelegate.m
這個類中定義了應用程式生命周期中各個事件的執行方法:
- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions;程式啟動之後執行,隻有在第一次程式啟動後才執行,以後不再執行;
- (void)applicationwillresignactive:(uiapplication *)application;程式将要被激活時(獲得焦點)執行,程式激活使用者才能操作;
- (void)applicationdidenterbackground:(uiapplication *)application;程式進入背景後執行,注意進入背景時會先失去焦點再進入背景;
- (void)applicationwillenterforeground:(uiapplication *)application;程式将要進入前台時執行;
- (void)applicationdidbecomeactive:(uiapplication *)application;程式被激活(獲得焦點)後執行,注意程式被激活時會先進入前台再被激活;
- (void)applicationwillterminate:(uiapplication *)application;程式在終止時執行,包括正常終止或異常終止,例如說一個應用程式在後太運作(例如音樂播放軟體、社交軟體等)占用太多記憶體這時會意外終止調用此方法;
為了示範程式的生命周期,不妨在每個事件中都輸出一段内容,簡單調整上面的代碼:
下面是各個不同操作的運作結果:
相信通過上面運作過程大家會對整個運作周期有個大概了解。比較容易混淆的地方就是應用程式進入前台、激活、失去焦點、進入背景,這幾個方法大家要清楚。如果一個應用程式失去焦點那麼意味着使用者目前無法進行互動操作,是以一般會先失去焦點再進入背景防止進入背景過程中使用者誤操作;如果一個應用程式進入前台也是類似的,會先進入前台再獲得焦點,這樣進入前台過程中未完全準備好的情況下使用者無法操作。另外一般如果應用程式要儲存使用者資料會在登出激活中進行(而不是在進入背景方法中進行),因為如果使用者輕按兩下home不會進入背景隻會登出激活;如果使用者恢複應用狀态一般在進入激活狀态時處理(而不是在進入前台方法中進行),因為使用者可能是從工作列直接傳回應用,此時不會執行進入前台操作。
當然,上面的事件并不是所有appdelegate事件,而是最常用的一些事件,其他事件大家可以查閱官方文檔,例如-(void)applicationdidreceivememorywarning:(uiapplication *)application;用于在記憶體占用過多發出記憶體警告時調用并通知對應的viewcontroller調用其記憶體回收方法。這裡簡單以圖形方式描述一下應用程式的調用過程:
這裡對于xcode預設為我們生産的項目結果檔案做一下簡單介紹:
appdelegate(.h/.m):應用程式代理,主要用于監聽整個應用程式生命周期中各個階段的事件;
viewcontroller(.h/.m):視圖控制器,主要負責管理uiview的生命周期、負責uiview之間的切換、對uiview事件進行監聽等;
main.storyboard:界面布局檔案,承載對應uiview的視圖控件;
images.xcassets:應用程式圖像資源檔案;
info.plist:應用程式配置檔案;
main.m:應用程式入口函數檔案;
xxx-prefix.pch:項目公共頭檔案,此檔案中的導入語句在編譯時會應用到所有的類檔案中,相當于公共引入檔案(注意在xcode6中沒有提供此檔案)
關于appdelegate、main.m前面已經介紹過了,viewcontroller和main.storyboard在後面介紹,這裡先說一下image.xcassets檔案。在xcode中打開這個檔案會發現裡面有兩個設定項:appicon和launchimage
在appicon中可以看到三個圖示設定,當我們勾選了右側ios6.1 and prior sizes或者其他選項這個圖示會自動增多,也就是說可以設計的圖示跟應用程式準備支援的裝置系統有關,這裡我們就以預設的ios7為例(現在基本上裝置都更新到ios7了):
a.iphone spotlight-ios5,6 settings-ios 5-7 29pt:用于設定ios5或者ios6的搜尋圖示以及ios5、ios6、ios7的設定圖示,大小是58*58。
ios搜尋圖示:
ios設定圖示:
b.iphone spootlight ios 7 40pt:設定ios7的搜尋圖示,大小是80*80。具體參見上圖。
c.iphone app ios7 60pt:設定ios7的應用圖示,大小是120*120。
ios應用圖示:
在launchimage中兩個圖示設計主要用于豎屏啟動圖
a.iphone portraint ios7 2x:大小為640*1136的啟動圖檔;
b.iphone portraint ios7 r4:大小為640*960的啟動圖檔;
其實上面的圖檔并不是所有圖檔都必須設定,具體要求可以直接檢視蘋果官方要求,例如這裡我們設定應用圖示和r4啟動圖檔後具體效果如下(這裡使用的圖示取材來自微信):
上面我們添加了一個應用圖示和一個啟動圖檔,在images.xcassets上右鍵在fiddler中檢視檔案内容并進入images.xcassets檔案夾,可以看到兩個子檔案夾:appicon.appiconset和launchimage.launchimage,如下圖:
兩個檔案夾中分别存放了我們前面設定的圖檔資源,除此之外還各有一個contents.json檔案,在這個檔案中記錄的資源資訊,例如appicon.appiconset檔案夾中的contents.json内容如下,這裡記錄了每個圖示的大小名稱等資訊:
info.plist檔案記錄了應用程式的配置資訊,如下圖:
其實這些資訊我們可以在項目屬性中進行配置,效果和編輯這個文檔是一樣的,大家可以對照檢視:
到目前為止我們還沒有解釋我們的程式是如何顯示預設視圖界面的。做過winform程式的朋友都知道每個window視窗界面都有一個設計器(對應一個設計檔案),其實在ios中也可以通過設計工具設計界面不用編寫代碼,這個工具就是interface builder。用interface builder編輯的檔案在ios5之前是一個“.xib”檔案,從ios5開始進行了改進,使用“.storyboard”檔案進行設計。其實在上面我們已經看到這個檔案,這裡重點說明一下storyboard檔案的使用。
首先我們打開main.storyboard,此時可以看到一個interface builder界面設計器出現在我們眼前:
在這個界面中整個核心就是右側視圖控制器viewcontroller,在viewcontroller中有一個視圖uiview,這個視圖用來放置其他使用者操作控件。視圖控制器左側的箭頭表示這個視圖控制器是個主視圖控制器,程式啟動之後預設就會直接顯示這個視圖控制器的視圖。我們可以在項目屬性中通過修改“main interface”屬性來修改主視圖控制器。
這裡我們不妨從xcode右側工具欄object library中拖放一些元件在上面簡單完成一個登入布局。
要實作這個登入,那麼接下來就是事件和屬性綁定的問題,大家應該可以猜到登入的邏輯代碼肯定在viewcontroller.m中編寫,那麼storyboard檔案是如何關聯到這個類的呢?如果我們在storyboard界面選中viewcontroller在xcode右側切換到identity inspector視圖就會發現裡面目前設定的是viewcontroller類,通過這個設定main.storyboard和viewcontroller關聯在一起。
那麼如何在代碼中讀取兩個textfield的值并通過點選按鈕觸發相關事件驗證登入合法性呢?要想在代碼中使用uitextfield,并且添加按鈕點選事件,則必須在viewcontroller.h中定義兩個uitextfield屬性和一個登入方法。
上面代碼我們需要解釋一下iboutlet、ibaction,其餘代碼和我們之前寫的objc沒有任何差別。
iboutlet:iboutlet沒有做任何操作,它的唯一作用就是告訴interface builder這個屬性可以被關聯到其中某個控件(在代碼中可以看到代碼前面多了空心圓點)。
ibaction:其實就是void,隻是當你定義為ibaction在interface builder中可以關聯到某個控件的事件方法(後面的關聯操作将會看到,而且我們在代碼中也可以看到代碼前面多了空心圓點);
下面看一下storyboard中的控件和代碼中定義的屬性和事件如何關聯。xcode為我們提供了幾種方式來實作代碼和storyboard控件的關聯:
1.拖拽控件到代碼中(首先點選xcode右上方“show the assistant editor”切換對應視圖,然後在代碼中打開.h檔案,同時打開interface builder,按住ctrl鍵拖拽控件到代碼中相應的位置進行關聯),關聯後屬性或方法前的空心圓變成實心表示已經關聯到具體控件(注意:事實上,從控件拖拽到代碼時如果代碼中沒有定義對應的屬性和方法interface builder會自動生成代碼)。
2.從控件場景中拖拽控件到代碼,關聯後屬性或方法前的空心圓變成實心表示已經關聯到具體控件。(在interface builder中點選左下角“show document outline”顯示控件結構樹,選中相應的控件按住ctrl鍵拖拽到代碼中的屬性或方法上)
3. 在控件上右鍵找到對應的屬性或方法關聯到代碼中對應的屬性或方法即可,關聯後屬性或方法前的空心圓變成實心表示已經關聯到具體控件。
4.與方法3類似,不再截圖,隻是通過view control scene中的控件右鍵來關聯,關聯後屬性或方法前的空心圓變成實心表示已經關聯到具體控件。(在interface builder中點選左下角show document outline顯示控件結構樹,選中相應的控件右鍵拖拽到代碼中的屬性或方法上)
5.對于前面幾種方法其實我們還可以直接從代碼拖拽到控件上面,這裡簡單示範一種,其他情況大家可以自己試驗。
如果要删除關聯,可以采用第三、第四種方式在控件上右鍵,在關聯菜單中找到對應的關聯删除即可。此外需要注意對于一個控件而言可能有多個事件,當我們使用第三種或第四種方式直接選擇具體某個事件關聯到login:方法自然沒有問題,但是第一、第二、第五種方式沒有提示我們關聯到哪個事件而是使用一個控件的預設事件(對于uibutton就是touch up inside事件)。
既然控件和代碼屬性或方法已經做了關聯,這裡我們看一下具體效果,這裡簡單修改一下viewcontroller.m
這裡實作了login:方法模拟登入的過程,可以發現當在手機号碼中輸入“123”,在密碼中輸入“456”點選登入會輸出”登入成功!“。
storyboard進行界面設計固然不錯,特别是對于初學者經常會使用設計器進行界面設計,但是實際開發過程中我們很多情況下會直接使用代碼進行界面布局,特别是對于複雜的界面布局更是如此。下面我們就從一個空項目建立一個類似于前面的登入界面。
直接在xcode中建立“empty application”(注意在xcode6中這個選項已經沒有了,這裡采用xcode5.1),此時會發現已經沒有viewcontroller和storyboard檔案,我們需要手動建立一個視圖控制器(在項目中右鍵選擇objective-c class,預設繼承自uiviewcontroller,輸入類名:kcmainviewcontroller即可)。
建立的視圖控制器預設情況下是無法加載到程式運作界面上的,此時需要在應用程式代理的程式加載完畢事件中手動加載并顯示我們的視圖。修改之前kcappdelegate.m代碼如下:
我們修改上面- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions的代碼如下:
然後在我們自定義的kcmainviewcontroller.m中添加一個uiimageview、兩個控件uitextfield和一個uibutton控件,并且實作具體的登入方法。
kcmainviewcontroller.h
kcmainviewcontroller.m
運作效果如下,與之前使用storyboard建立的界面類似,同時也能點選登入:
在這裡我們需要對上面的代碼一樣解釋,在弄清上面的代碼之前我們不得不熟悉一個uikit中最重要的類uiview。
uiview就是指界面可見的控件元素,所有的控件最終都繼承自uiview,uiview中還可以添加其他uiview(通過addsubview方法);
在一個ios應用中必須有一個主視窗uiwindow(理論上也可以有多個uiwindow但是隻有一個是主window,而且隻有主window可以和使用者互動),uiwindow也是繼承自uiview,它擁有uiview的所有屬性、方法;
在uiwindow中必須有一個根控制器,這個控制器距離uiwindow是最近的;設定一個控制器為根控制器和直接通過addsubview添加控制器的視圖(view屬性)到window并不完全一樣(例如如果僅僅添加控制器視圖那麼應用雖然可以顯示但是不支援旋轉);
uiviewcontroller是視圖控制器,主要用來控制uiview,在uiviewcontroller内部有一個uiview(view屬性);
在上面的代碼中我們首先在應用程式加載完畢之後加載一個uiwindow對象,同時把我們的視圖控制器kcmaincontroller設定為uiwindow的根視圖控制器,然後設定這個uiwindow為主視窗并可見。當主視窗設定為可見過程中會調用視圖控制器的loadview方法來加載視圖(注意視圖控制器的loadview方法是延遲加載的,第一次調用視圖控制器的view屬性才會調用此方法;由于makekeyandvisible方法中會使用視圖控制器的view屬性是以此時會調用視圖控制器的loadview方法),視圖加載完之後調用viewdidload方法,在這個方法中我們添加登入相關控件并将這些控件加載到視圖控制器kcmainviewcontroller的視圖view中。
下面我們看一下應用程式最終的布局,相信通過這張圖大家對于ios的布局會有一個大緻了解:
2.應用程式圖像資源尺寸--其實關于圖檔尺寸規定我們可以直接檢視xcode自帶幫助文檔,例如可以檢視“icon and image sizes”一節獲得圖檔大小說明:
3.模拟器檔案存儲的位置--模拟器中為什麼可以運作我們的程式,程式到底在什麼位置?
這些檔案其實在mac中 os x中是隐藏的,首先通過“defaults write com.apple.finder appleshowallfiles -bool true”指令顯示隐藏檔案(關閉隐藏檔案顯示通過“defaults write com.apple.finder appleshowallfiles -bool false”指令),然後到“/users/kenshincui/library/application support/iphone simulator/7.1/applications”檔案夾中會看到很多guid命名的檔案夾,隻要一個一個檢視就可以找到我們的程式。模拟器運作時會加載這個檔案夾中的應用程式包顯示到模拟器中。
可以看到在上圖中有一個iosbycode的應用程式包,我們可以通過“顯示包内容”檢視具體程式資源:
4.uiapplication--前面一直提到uiapplication對象,這個對象在ios中是一個單例,我們通過[uiapplication sharedapplication]獲得(注意在ios開發中一般以shared開頭的對象都是單例)。這裡列舉一些uiapplication的常用方法:
例如調用applicationiconbadgenumber方法之後效果如下: