UI控件進階1——程序啟動原理

數據選擇控件


  • 數據選擇控件?

    1. 幫助用戶快速選擇數據的控件。
    2. UIPickerView——顯示一組或多組數據方便用戶選擇。
    3. UIDatePicker——顯示一個日期組件方便用戶選擇。

  • UIPickerView——數據選擇視圖

    1. 作用:
      • 從指定的數據源中選擇數據。
      • 通常以UITextField的inputView的形式出現(當選中某個文本框后,彈出鍵盤中顯示該控件)。
    2. 注意:
      • 使用PickerView之前需要指定數據源對象和代理對象。
      • 需要使用到的兩個協議:UIPickerViewDataSource數據源協議,UIPickerViewDelegate數據源代理協議。
    3. 隨機生成數字arc4random()
      • 這是個C語言函數。
      • 隨機生成一個無符號整數(0或所有正整數)。
      • 隨機生成一個0~n之間的數字:
        • arc4random() % (n + 1)
        • arc4random_uniform(u_int32_t)
// UIPickerView的數據源方法 @required
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView; // 設置UIPickerView共有幾列
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component; // 設置每列中有幾行

// UIPickerView的代理方法 @optional
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component; // 每行的數據內容
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component; // 監聽PickerView的選擇事件
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view; // 自定義每行顯示的樣式

// UIPickerView的對象方法
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated; // 選中指定component列中的row行,滾動到指定的行,不會觸發代理方法
- (NSInteger)selectedRowInComponent:(NSInteger)component; // 返回當前列的選中行的索引
- (void)reloadAllComponents; // 重新加載所有列的數據
- (void)reloadComponent:(NSInteger)component; // 重新加載指定列的數據

  • UIDatePicker——方便用戶選擇日期

    1. 作用:

      • 方便用戶日期選擇,并保證日期格式正確。
      • 通常以UITextField的inputView的形式出現。
    2. 自定義文本框的彈出鍵盤:

      • 通過設置UITextField的inputView屬性來修改當文本框獲得焦點后,彈出什么控件。
      • 設置該屬性的值為UIDatePicker控件(動態創建一個UIDatePicker控件,無需設置高寬),這樣就可以實現當文本框獲得焦點后,自定義彈出鍵盤了。
    3. 自定義鍵盤上的工具控件:

      • 設置文本框的inputAccessoryView屬性即可。
      • 工具條的使用:UIToolbar(barTintColor,從iOS7開始;backgroundColor繼承自UIView,從iOS2開始)。
      • Accessory,表示“附件”、“裝飾品”的意思。
      • 在UIToolbar中只能放UIBarButtonItem,工具條一般用在鍵盤上面。
      • 設置某個BarButtonItem顯示在最右邊:在最右邊的BarButtonItem之前插入一個BarButtonItem,并設置該BarButtonItem的Identifier的值為Flexible Space。
      • 工具條一般用在鍵盤上面。
      • 創建好工具條以后要設置工具條的frame。
@property (nonatomic) UIDatePickerMode datePickerMode; // 日期選擇模式,默認UIDatePickerModeDateAndTime
@property (nonatomic, retain) NSLocale *locale; // 語言環境,默認[NSLocale currentLocale]
@property (nonatomic, retain) NSDate *date; // 默認是創建控件時的當前系統日期
@property (nonatomic, retain) NSDate *minimumDate; // 指定min/max日期范圍。默認為nil。如果 min > max,指定的數值會被忽略。在UIDatePickerModeCountDownTimer模式無效
@property (nonatomic, retain) NSDate *maximumDate; // 默認為nil
@property (nonatomic) NSTimeInterval countDownDuration; // 用于UIDatePickerModeCountDownTimer模式,默認是0.0,最大不能超過23:59 (86,399 秒)。設置數值以分鐘為單位
@property (nonatomic) NSInteger minuteInterval; // 間隔分鐘,最小1,最大30
- (void)setDate:(NSDate *)date animated:(BOOL)animated; // 設置日期(動畫)

程序的啟動原理

  • 項目中的常見文件?

    1. xxxxTest文件夾用來做單元測試。
    2. Products目錄:在Mac程序下,生產的可執行文件app會存放到該目錄下,iOS程序產生的是ipa文件,Products目錄對于iOS程序來說意義不大。
    3. Info.plist,全局配置文件,非常重要,不能刪除,注意自己創建的plist文件中不要包含Info關鍵字。Info.plist中的一些配置項:
      • Bundle display name(在Xcode6中叫做“Bundle name”),表示軟件裝到手機上后,顯示的名稱。當修改了該名稱后,為了保證有效,點擊Product->Clean,同時將軟件從模擬器中卸載掉,然后再重新運行。
      • Bundle Identifier,app的唯一標示。
      • Bundle Version,每次發布軟件的版本號。
      • Main storyboard file base name,對應的就是選中“項目”->“General”->“Deployment Info”->“Main Interface”中的設置。
      • Supported interface orientations,標識設備所支持的方向,對應的選中“項目”->“General”->“Deployment Info”->“Device Orientation”。iPhone只支持三種方向,Portrait(豎屏)、Landscape Left(橫屏向左)、Landscape Right(橫屏向右)。
      • Info.plist文件本質就是一個xml文件。
    4. pch文件:(Prefix Header File)(頭文件):
      • 遇到的問題:①整個項目中很多地方都在使用某個類的頭文件;②整個項目中很多地方都在使用同一個“宏”;③在項目中很多地方用到了NSLog()函數,想快速清除。
      • 解決上面的問題,可以通過使用pch文件,pch文件就是一個頭文件(類似于*.h文件)。
      • 注意:pch文件的特點,項目中的所有其他代碼文件無需導入該pch文件,默認就都可以訪問(其他文件無需手動#import該pch文件就能使用)。
      • 主要作用:可以放一些公用的宏定義;把公共的Model類的#import導入寫到pch文件中;自定義NSLog()(例如:#define LNLog(...) NSLog(VA_ARGS))。
      • 在Xcode6.1中,默認沒有創建pch文件,創建方式:"New File"->"Other"->"PCH File"->"PrefixHeader.pch"。
      • 選中項目->Build Setting->All->搜索"prefix head"->修改Prefix Header的內容為:"$(SRCROOT)/$(PRODUCT_NAME)/PrefixHeader.pch"或者"$(SRCROOT)/對應的文件夾名/PrefixHeader.pch"。
    5. 補充,程序開發階段分為:
      • 調試階段:寫代碼、調錯誤,需要使用NSLog(),同時在調試階段系統會自定義一個叫做DEBUG的宏。
      • 發布階段:寫好的代碼生成ipa等壓縮文件,上傳到AppStore,安裝到用戶設備上,不需要NSLog(),同時系統會自動刪除叫做DEBUG的宏。

  • UIApplication對象介紹?

    1. 一個UIApplication代表是一個應用程序,而且是單例的,用來封裝整個應用程序的一個對象,比如當應用程序執行到某個時期要做什么,生命周期等。
    2. 獲取UIApplication對象:[UIApplication sharedApplication];(單例的)。
    3. 當一個iOS程序啟動后,首先創建的第一個對象就是UIApplication對象。
    4. 利用UIApplication可以做一些應用級別的操作:
      • 如應用程序右上角的角標;
      • 聯網操作時,狀態欄上的等待圖標指示器;
      • 利用UIApplication打開某個資源;
      • 通過UIApplication管理狀態欄,iOS7開始狀態欄默認交給了控制器來管理,如果希望通過UIApplication來管理,需要在Info.plist文件中增加一個配置項* View controller-based status bar appearance = NO
// 獲取UIApplication對象
UIApplication *app = [UIApplication sharedApplication];

// iOS8系統要求設置通知的時候必須經過用戶許可
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
[app registerUserNotificationSettings:settings];
// 設置右上角,有10條消息
app.applicationIconBadgeNumber = 10;

// 聯網操作時,狀態欄上的等待圖標指示器,waiting圖標
app.networkActivityIndicatorVisible = YES;

// 利用UIApplication打開某個資源,系統會自動根據協議識別使用某個app打開
[app openURL:[NSURL URLWithString:@"http://www.baidu.com"]];

// 設置狀態欄是否隱藏
app.statusBarHidden = YES;

  • UIApplicationDelegate介紹?

    1. 新建完項目以后AppDelegate文件,就是UIApplication的代理對象,并且該代理對象已經被設置好了,無需我們手動設置。
    2. AppDelegate的主要作用就是處理(監聽)應用程序本身的各種事件:應用程序啟動完畢,應用程序進入后臺,應用程序進入前臺,內存警告等,都是應用程序自身的一些事件。
    3. 要想成為UIApplication的代理對象,必須遵守:UIApplicationDelegate協議。
// app第一次啟動完畢后就會調用(當程序啟動后會顯示一張啟動圖片, 當這個圖片顯示完畢, 消失后, 就開始調用這個方法)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
// 當程序進入后臺時,調用該方法,在這個方法中可以做一些保存當前程序數據, 暫停程序的操作
- (void)applicationDidEnterBackground:(UIApplication *)application;
// 當程序再次進入前臺的時候調用
- (void)applicationWillEnterForeground:(UIApplication *)application;
// 當發生內存警告時觸發該事件
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;

  • UIApplicationMain函數介紹?
    1. 方法名:
int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
2. 參數介紹:
    * argc:使用main函數的argc即可。
    * argv:使用main函數的argv即可。
    * principalClassName:指定應用程序類名(app的象征),該類必須是UIApplication(或子類),如果為nil,則用UIApplication類作為默認值。
    * delegateClassName:指定應用程序的代理類,UIApplicationDelegate協議中定義的方法,在該類中實現。
3. UIApplicationMain函數會:
    * 根據principalClassName創建UIApplication對象。
    * 根據delegateClassName創建一個delegate對象,并將該delegate對象賦值給UIApplication對象中的delegate對象。
    * 代理參數必須傳遞,如果傳nil,則顯示“黑屏”。
// 默認調用方式
UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
// 等價于
UIApplicationMain(argc, argv, @"UIApplication", @"AppDelegate");

  • iOS程序啟動過程?

    1. 打開程序。
    2. 調用main函數。
    3. 在main函數中調用:UIApplicationMain()函數。
      • 在UIApplicationMain()函數中:
        • 創建UIApplication對象。
        • 創建AppDelegate代理對象。
        • 將AppDelegate代理對象設置給UIApplication對象。
        • 在UIApplicationMain()函數開啟一個“死循環(事件循環)”,所以程序不會退出,可以任意使用,在這個“死循環(事件循環)”中程序不斷監聽用戶的各種事件,依次處理(依靠“事件隊列”實現)。
        • 程序啟動完畢,觸發application:didFinishLaunchingWithOptions:事件。
      • 程序退出。

  • UIWindow對象?

    1. UIWindow是一中特殊的UIView,UIWindow也是繼承自UIView。
    2. 通常一個app只會有一個UIWindow對象。
    3. iOS程序啟動完畢后,創建的第一個視圖控件就是UIWindow,接著創建控制器的view,最后將控制器的view添加到UIWindow上,于是控制器的view就顯示在屏幕上了。
    4. 一個iOS程序之所以能顯示到屏幕上,完全是因為它有UIWindow。
    5. 創建過程UIWindow->UIViewController->UIView->把UIView加到UIWindow對象中。
    6. 將控制器的view添加到UIWindow中:
      • 方式一:直接把控制器的view添加到UIWindow中,此方法不推薦,因為當方法執行完畢后控制器就釋放了,但是控制器的view還在,當手機旋轉的時候,界面中的內容不會跟著旋轉,UIView中的各個子控件的事件監聽程序都寫在了一個類中,無法分為多個控制器來管理。
      • 方式二:通過設置UIWindow的根控制器的方式(推薦)。
    7. 如果不使用控制器,直接把控件添加到UIWindow中行不行?可以的,但是不推薦。因為如果把所有控件都直接加到UIWindow上,那么很多個界面,每個界面的各種事件監聽都交給了同一個類來處理了。
    8. 總結:UIWindow就一個作用“顯示界面”,將來是通過切換不同的控制器view分別顯示到UIWindow上。

  • 總結程序啟動的完整過程?

    1. 沒有storyboard文件:
      • 調用main函數。
      • 調用UIApplicationMain函數。
      • 創建UIApplication對象,AppDelegate對象。
      • 設置UIApplication對象的代理是AppDelegate對象。
      • AppDelegate對象開始監聽“系統事件(應用程序的事件)”,進入“事件循環”。
      • 程序啟動完畢后調用application: didFinishLaunchingWithOptions:方法。
      • application: didFinishLaunchingWithOptions:方法中創建:UIWindow、控制器、設置UIWindow的根控制器是剛才創建的控制器、顯示UIWindow。
    2. 有storyboard文件:
      • 調用main函數。
      • 調用UIApplicationMain函數。
      • 創建UIApplication對象、AppDelegate對象。
      • 設置UIApplication對象的代理是AppDelegate對象。
      • AppDelegate對象開始監聽“系統事件(應用程序的事件)”,進入“事件循環”。
      • 程序啟動完畢后調用application: didFinishLaunchingWithOptions:方法。
      • application: didFinishLaunchingWithOptions:方法中創建:
        • 系統自動創建UIWindow對象。
        • 根據Info.plist文件配置(Main Interface),找到需要加載的storyboard文件(Main.storyboard)。
        • 找到Main.storyboard中的Is Initial View Controller對應的控制器類,創建該控制器對象。
        • 根據storyboard中的配置,創建控制器對應的view。
        • 設置UIWindow的根控制器(rootViewController)為剛才創建的控制器。
        • 顯示UIWindow([self.window makeKeyAndVisible];)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容