iOS基礎 - iOS程序啓動原理

1、UIApplicationMain

main.mmain函數中執行了UIApplicationMain這個方法,這是ios程序的入口點ios

int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName)編程

argcargvISO C標準main函數的參數,直接傳遞給UIApplicationMain進行相關處理便可windows

principalClassName:指定應用程序類,該類必須是UIApplication(或子類)。若是爲nil,則用UIApplication類做爲默認值app

delegateClassName:指定應用程序類的代理類,該類必須遵照UIApplicationDelegate協議框架

此函數會根據principalClassName建立UIApplication對象,根據delegateClassName建立一個delegate對象,並將該delegate對象賦值給UIApplication對象中的delegate屬性編輯器

UIApplication對象會依次給delegate對象發送不一樣的消息,接着會創建應用程序的main runloop(事件循環),進行事件的處理(首先會調用delegate對象的 application:didFinishLaunchingWithOptions:)ide

程序正常退出時這個函數才返回。若是進程要被系統強制殺死,通常這個函數還沒來得及返回進程就終止了函數

 

2、UIApplication

UIApplication是應用程序的核心,每個程序在運行期必須有UIApplication(或子類)的一個實例(有且僅有一個),經過[UIApplication sharedApplication]能夠獲得這個單例實例的指針oop

UIApplication幫助管理應用程序的生命週期,而它經過delegate來履行這個任務動畫

UIApplication能夠接收事件,把全部用戶事件都放入隊列,逐個處理,它會發送當前事件給一個合適的目標控件進行處理。它還將部分事件轉給delegate對象來處理,delegate可處理的事件包括:應用程序的生命週期事件(如程序啓動和關閉)、系統事件(如來電)

[UIApplication sharedApplication].windows: 在本應用中打開的UIWindow列表,這樣就能夠接觸應用中的任何一個UIView對象

[UIApplication sharedApplication].keyWindow: 用來接收鍵盤以及非觸摸類的消息事件的UIWindow,並且程序中每一個時刻只能有一個UIWindowkeyWindow。若是某個UIWindow內部的文本框不能輸入文字,多是由於這個UIWindow不是keyWindow

 

3、UIApplicationDelegate

在開發過程當中,UIApplication是一個很是重要的全局對象。但在實際編程中咱們並不直接和UIApplication對象打交道,而是和其代理打交道,它的代理必須遵照UIApplicationDelegate協議,代理提供了相關的生命週期方法來處理應用程序的系統事件

ios設備的內存極其優先,若是爲app分配了太多內存,操做系統會終止app的運行,在UIApplication接收到這個事件後它會調用代理的applicationDidReceiveMemoryWarning方法,代理在這個方法內能夠進行釋放內存的操做以防止操做系統強制終止應用程序的運行

ios並非多任務的操做系統,因此app很容易受到打擾。好比一個來電可能致使app失去焦點,若是這個時候接聽了電話,那麼app會自動終止運行

還有不少其它相似的事件會致使app失去焦點

app失去焦點前會調用代理的applicationWillResignActive

app再次獲取焦點時會調用代理的applicationDidBecomeActive

在運行app時鎖屏會調用代理的applicationWillResignActive

當屏幕被解鎖時,會調用代理的applicationDidBecomeActive

 

4、UIWindow

UIWindow是一種特殊的UIView,一般在一個app中只會有一個UIWindow,但能夠手動建立多個UIWindow

UIWindow的主要做用:

提供一個區域來顯示視圖

將事件分發給視圖

UIViewController協同工做,方便完成設備方向旋轉的支持

添加UIViewUIWindow中兩種常見方式:

addSubview:直接將UIView添加到UIWindow中,程序負責維護UIView的生命週期以及刷新,但並不會理會UIView對應的UIViewController

rootViewController:自動將UIViewController對應的UIView添加到UIWindow中,同時負責維護UIViewControllerUIView的生命週期

經常使用方法

makeKeyWindow:讓當前UIWindow變成keyWindow

makeKeyAndVisible:讓當前UIWindow變成keyWindow,並顯示出來

 

5、UIViewController

UIViewController屬於MVC模型中的C(Controller),說的更具體點它是一個視圖控制器,管理着一個視圖(UIView)

一個UIViewController應該只管理一個view hierarchy,一般來講一個完整的view hierarchy指的是佔滿整一個屏幕。而不少app滿屏中會有各個區域分管不一樣的功能,一些開發者喜歡直接新建一個UIViewController和一套相應的view來完成所要的功能,這樣作徹底不符合Apple提供的設計規範

 

6、UIViewControllerview

能夠利用xib文件來初始化view; 也可使用自定義的view,那就必須覆蓋loadView方法來建立這個view

UIViewControllerviewlazy loading,當你訪問其view屬性時,view會從xib文件載入或者經過代碼建立(覆蓋loadView方法,自定義其view hierarchy) 

能夠用isViewLoaded方法判斷一個UIViewControllerview是否已經被加載

 

7、UIViewController生命週期方法的調用

view加載後調用viewDidLoad,這裏能夠進行一些數據的請求或加載,用來更新界面

view將要被加入view hierarchy時調用viewWillAppear,完成加入時調用viewDidAppear

view將要從view hierarchy中移除時調用viewWillDisappear,完成移除時調用viewDidDisappear

當內存緊張時調用didReceiveMemoryWarning,其默認實現是若是當前UIViewControllerviewsuperviewnil,則將view釋放且調用viewDidUnload, viewDidUnload中你能夠進行後繼的內存清理工做(主要是界面元素的釋放,當再次加載的時候須要重建)

(這裏的view是指UIViewController內部的view屬性)

 

8、工程名-Info.plist

創建一個工程後,會在Supporting files文件夾下看到一個」工程名-Info.plist」的文件,該文件對工程作一些運行期的配置,很重要,不能刪除

在舊版本Xcode建立的工程中,這個配置文件的名字就叫」Info.plist

若是使用文本編輯器打開這個文件,會發現這是一個XML格式的文本文件,通常不用文本編輯器直接編輯這個文件,而是經過Xcode編輯

項目中還有一個InfoPlist.strings的文件,跟Info.plist文件的本地化相關

常見屬性(紅色部分是用文本編輯器打開時看到的key)

Localiztion native development region(CFBundleDevelopmentRegion)-本地化相關

Bundle display name(CFBundleDisplayName)-程序安裝後顯示的名稱,限制在1012個字符,若是超出,將被顯示縮寫名稱

Icon file(CFBundleIconFile)-app圖標名稱,通常爲Icon.png

Bundle version(CFBundleVersion)-應用程序的版本號,每次往App Store上發佈一個新版本時,須要增長這個版本號

Main nib file base name(NSMainNibFile)-nib文件的名稱

Bundle identifier(CFBundleIdentifier)-項目的惟一標識,部署到真機時用到

 

9、工程名-Prefix.pch

通常來講,能夠將項目中常常用到的一些頭文件放在這裏來import,整個項目均可以訪問這個文件的內容,這樣既節省了手動添加import的時間,也有助於加速編譯

在這裏定義的宏,整個項目均可以訪問

pch文件中添加下列預處理指令,而後在項目中使用Log()來輸出日誌信息,就能夠在發佈應用的時候,一次性將NSLog語句移除(在調試模式下,纔有定義DEBUG

#ifdef DEBUG

#define Log(...) NSLog(__VA_ARGS__)

#else

#define Log(...) /* */

#endif

 

10、開發iOS6的注意

iOS6新特性:auto layout屬性,此屬性只針對iOS6及以上版本 

iOS6如下版本運行時可能會出現的異常信息:

Terminating app due to uncaught exception NSInvalidUnarchiveOperationException, reason: Could not instantiate class named NSLayoutConstraint 

具體場景:Xcode 4.5 選擇iPhone/iPad 5.0/5.1 Simulator(模擬器) 

解決辦法:須要關閉storyboardxib界面文件的Use Autolayout 選項,這是由於Auto Layout特性是iOS 6新增長的,在以前的 5.0/5.1 Simulator模擬器中不支持

 

11、nib文件

nib文件是iOS中用來描述視圖的xml格式的文本文件,如今拓展名爲xib,用Interface Builder打開能夠生成圖形界面式的描述

某書中著名的一句話:Interface Builder把窗口、菜單欄以及窗口上的各類控件對象都」凍結」在一個NIB文件裏;程序運行時,這些對象將會」甦醒」

加載Nib文件時,會將文件中的描述轉化爲應用程序能夠操做的真正對象,全部在Interface Builder中創建的關聯(如Files Owner和其餘對象之間的關聯)都可以在運行時從新創建起來

 

12、主nib文件

nib文件是指應用程序一啓動就裝載的nib文件,它的Files Owner必定要是個UIApplication(或子類),而且新建一個delegate對象、創建UIApplicationdelegate對象的關聯

 

十3、UIView

UIViewiOS中界面元素的基礎,全部的界面元素都繼承它,能夠說在iPhone中你能看到的、摸到的,都是UIView

UIView的基本功能:

繪圖和動畫(CALayerCAAnimation實現)

事件處理(繼承了UIRsponder)

一個UIView能夠包含和管理若干個子視圖,決定着子視圖的位置和大小

 

十4、UIView經常使用方法和屬性

frame 

在父視圖座標系中的位置(CGPoint origin)和大小(CGSize size)

bounds

在本視圖座標系中的位置(CGPoint originxy永遠爲0)和大小(CGSize size)

center

視圖的中點在父視圖座標系中的位置

UIView *superview 父視圖

NSArray *subviews 全部的子視圖

UIWindow *window  當前視圖所在的窗口

BOOL userInteractionEnabled YES表明接收觸摸事件

- (void)removeFromSuperview

從父視圖中移除(當前視圖的計數器會-1)

- (void)addSubview:(UIView *)view

添加一個子視圖(新添加的子視圖在父視圖的最上面,子視圖的計數器會+1)

- (UIView *)viewWithTag:(NSInteger)tag

根據tag找到對應的子視圖

 

十5、UIKit座標系

View1View2的父視圖

View2.frame = {x=70,y=50,width=60,height=40}

View2.bounds = {x=0,y=0,width=60,height=40}

View2.center = (x=100, y=70)

UIKit框架中的座標系都如左圖所示,視圖的左上角爲原點(0,0)x軸向右正向延伸,y軸向下正向延伸

View3framexy:

若是綠色視圖是View3的父視圖,那麼View3xy爲紅色箭頭的長度

若是View1View3的父視圖,那麼View3xy爲藍色箭頭的寬度

 

十6、iOS關閉鍵盤

方法1

調用UIViewendEditing方法,例如

[self.view endEditing:YES];

成功關閉鍵盤的條件:self.view或者其子視圖是第一響應者

方法2

遞歸找到第一響應者,讓它把鍵盤給退回去

[[self findFirstResponder:self.view] resignFirstResponder];

- (UIView*)findFirstResponder:(UIView*)view {

    for ( UIView *childView in view.subviews ) {  // 遍歷子視圖

    if ( [childView respondsToSelector:@selector(isFirstResponder)] 

&& [childView isFirstResponder] ) {  

            return childView; // 若是childView是第一響應者

 }

        UIView *result = [self findFirstResponder:childView];

        if (result)  return result;

    }

    return nil;

}

相關文章
相關標籤/搜索