天天看點

iOS 基礎01—項目檔案、applecation、啟動過程、VC生命周期

iOS 基礎01—項目檔案、applecation、啟動過程、VC生命周期

1 項目中常見的檔案

  • 1 info.plist 檔案

    plist檔案是一個全局配置檔案,系統預設就叫做info.plist,是以如果自己取名字千萬不可以取作info.plist;

    代碼裡拿到info.plist裡的參數使用

[[NSBundle mainBundle]infoDictionary]; //這個字典拿到的就是info.plist裡的東西,比如擷取版本号
NSString * versionStr = [[[NSBundle mainBundle]infoDictionary] objectForKey:@"CFBundleShortVersionString"];
           

另一個需要注意的是info.plist裡的Bundle name就是我們手機桌面上顯示的app名字,系統預設的是取product name

  • 2 .pch 檔案

    這是一個全局配置檔案,是需要自己手動建立的。在建立new file的最下面的other下有一個 pch file。生成完成之後,同樣需要自己配置一下。在build setting 裡搜 prefix header,把剛才自己建立的檔案名的路徑拖進去。

  • 3 OC宏

    這裡說的宏就是大概要用在PCH檔案裡面的使用到,自己以前沒見過的:

#ifdef __OBJC__ //OC檔案中使用
 #ifdef DEBUG //在debug條件下執行
 #define FCFLog(...) NSLog(__VA_ARGS__) //自定義的列印函數
 #else
 #define FCFLog(...) //NSLog(__VA_ARGS__)
 #endif
#endif
           
  • 4 這裡順帶提一下蘋果沙盒檔案裡的檔案目錄

Documents、Library、tmp這三個檔案夾。

1 Documents:蘋果建議将程式中浏覽到的資料儲存到該目錄下,對使用者可見。這個目錄用于存儲使用者資料或其他應該定期備份的資訊

2 Library:這個檔案夾下有兩個主要的子檔案夾Caches和Preferences。Preferences檔案放的就是平時我們用NSUserDefaults存取的東西;Caches則主要存取我們自己下載下傳的一些檔案資料。Library對使用者不可見。

3 tmp:是一個零時檔案夾。儲存app啟動過程中産生的資訊。

Documents和Library檔案夾在iCloud和iTunes備份的時候會被備份。tmp在iPhone重新開機或app記憶體不夠的時候就會被清空。

2 UIApplication

UIApplication 是應用程式啟動之後建立的第一個對象,且是單例對象。

大部分應用級别的設定都可以使用UIApplication進行設定

  • 1 設定應用程式圖示上的未讀通知數
UIApplication * app = [UIApplication shareApplication];
UIUserNotificationSettings * setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
[app registerUserNotificationSettings:settings];
app.applicationIconBadgeNumber = 99;
           
  • 2 設定應用程式狀态欄中正在請求網絡的旋轉小标志
UIApplication * app = [UIApplication shareApplication];
app.networkActivityIndicatorVIsible = YES;
           
  • 3 跳轉URL或app或打電話
//網址
UIApplication * app = [UIApplication shareApplication];
[app openURL:[NSURL URLWithString:@"https://www.baidu.com"] options:[[NSDictionary alloc] init] completionHandler:^(BOOL success) {
}]; 
//電話
[app openURL:[NSURL URLWithString:@"tel://10086"] options:[[NSDictionary alloc] init] completionHandler:^(BOOL success) {
}];
           
  • 4 AppDelegate 生命周期
1、didFinishLaunchingWithOptions      //app啟動完畢
2、applicationWillResignActive      //失去焦點:失去和使用者的互動能力
3、applicationDidEnterBackground      //app已經進入背景——一般用來儲存資料
4、applicationWillEnterForeground     //進入前台
5、applicationDidBecomeActive     //擁有焦點,恢複互動能力
6、applicationWillTerminate          //app銷毀的時候調用
     app啟動會調用: 1——5
     app進入背景依次調用: 2——3
     app進入前台依次調用: 4——5
     app殺死依次調用: 2——3——6
           

3 App啟動過程和原理

main函數之前:

作業系統iOS一開機就開始啟動一個系統的Runloop函數,以每秒60次的幀率不斷監聽這手機界面的使用者互動事件。一旦觸摸就會觸發一個觸摸事件,然後将事件放入事件隊列,緊接着就會通過端口找到對應的app,然後調用app的main函數——也就是OC檔案中的main.m檔案中的main函數

main函數:
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
           

main函數裡調用了UIApplicationMain函數。UIApplicationMain的第三個參數要麼是UIApplication,要麼是UIApplication的子類,第四個參數則是确定UIApplication的代理是誰。

UIApplicationMain
     UIApplicationMain函數則建立UIApplication對象,設定UIApplicationMainDelegate代理
     接着,開啟事件循環(消息循環) 開啟Runloop --> 加載info.plist -->如果設定了MainInterface,就加載對應的storyboard(建立window 建立初始化控制器)
           

4 Window

程式啟動過後建立的第一個視圖控件就是UIWindow,預設就是全屏的;

如果沒有在info.plist裡設定mian interface,那麼就得我們自己在app啟動之後(didFinishLaunchingWithOptions中)自己去建立一個window;

如果要讓window顯示則必須滿足兩個條件:

  • 1、給window設定rootViewcontroller;
  • 2、調用makekeyandvisible讓其可見:
_window = [[UIWindow alloc] init]; //預設的
_window.backgroundColor = [UIColorredColor];
_window.rootViewController = [[UIViewControlleralloc] init];
[_window makeKeyAndVisible];
           

程式會有多個window,但是隻有一個keywindow。而且是最後執行makeKeyAndVisible的window才是主視窗,注意這個和window的frame是沒有關系的:

建立第一個window

_window = [[UIWindow alloc] init]; //預設的
    _window.backgroundColor = [UIColor redColor];
    _window.rootViewController = [[UIViewController alloc] init];
    [_window makeKeyAndVisible];
           

建立第二個window

_window1 = [[UIWindow alloc] init]; //預設的
    _window1.backgroundColor = [UIColor blueColor];
    _window1.frame = CGRectMake(20, 20, 100, 200);
    _window1.rootViewController = [[UIViewController alloc] init];
    [_window1 makeKeyAndVisible];
           

在keywindow上加一個view

UIView * test = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
    test.backgroundColor = [UIColor yellowColor];
    [[UIApplication sharedApplication].keyWindow addSubview:test];
           

說明keywindow是window1

window有三個層級:UIWindowLevelNormal、UIWindowLevelAlert、UIWindowLevelStatusBar

如果沒有設定level,則window就是按照makeKeyAndVisible的調用順序依次添加進去的。如果設定了層級,則層級從最底層到最上層依次是UIWindowLevelNormal——UIWindowLevelStatusBar——UIWindowLevelAlert

5 ViewController

UIViewController的各種建立方式

  • 1、[alloc init]純代碼建立控制器,預設的frame就是全屏的,而且是透明色
FCFViewController * FCFVC = [[FCFViewController alloc]init];
           
  • 2、第二種方法,通過storyboard加載
UIStoryboard * sb = [UIStoryboard storyboardWithName:@"Test" bundle:nil];
01
 FCFViewController * FCFVC = [sb instantiateInitialViewController]; //這個函數傳回storyboard中initial(也就是箭頭所指的view controller,這裡需要自己去storyboad中把那個Is Initial View Controller勾上)的view controller
02
 FCFViewController * FCFVC = [sb instantiateViewControllerWithIdentifier:@"switch"]; 
//這個函數就是根據storyboard裡view controller的對應的Storyboard id辨別符拿到的view controller
           
  • 3、第三種方式,通過xib加載,這裡是建立View Controller不勾選建立xib,單獨建立一個xib
/* 建立一個xib,不要修改xib裡的任何東西
  *File's Owner :所有者,改成view controller的類名
  * 連線view :将xib的view作為所有者VC的view
  */
 FCFViewController * FCFVC = [[FCFViewController alloc] initWithNibName:@"Text" bundle:nil]; //這裡傳回的是控制器vc
           

6 View

  • 1、 純代碼 ,建立一個透明色,且frame和螢幕一樣大的view
TestViewController * vc = [[TestViewController alloc]init];
           
  • 2、sb建立,就是storyboard裡面的view
TestViewController * vc = [[UIStoryboard storyboardWithName:@"Test" bundle:nil] instantiateInitialViewController];
           
  • 3、xib 指定xib,view就是xib裡描述的一樣
TestViewController * vc = [[TestViewController alloc] initWithNibName:@"View" bundle:nil];
           
  • 4、xib 建立同名xib,就是在單獨建立xib的時候把xib的名稱寫成VC的名稱,同樣正常配置File’s owner 和 連線view, alloc init就可以了,系統會找同名的xib-“TestViewController”,如果沒有就加載同名的不帶Controller的xib-“TestView”.
TestViewController * vc = [[TestViewController alloc]init]; //先找TestViewController,再找TestView
           

7、ViewController生命周期

  • 1、這裡最關鍵的兩點就是loadView的執行時機和viewDidLoad的執行時機。

    loadView是懶加載,如果我們沒有在init方法是使用self.view,正常的加載順序就是init執行完之後——>執行loadview——>執行viewDidLoad。但是因為loadView是懶加載,是以在init方法裡面調用了self.view,那麼在用到self.view的時候就會馬上執行loadView,執行完loadView馬上會執行viewDidLoad,然後才傳回init方法裡執行self.view之後的代碼,執行個體:

@interface TestController ()
@property (nonatomic, assign)BOOL boolvalue;
@end

@implementation TestController

- (instancetype)init
{
  self = [super init];
  if (self) {
  NSLog(@"1");
  self.view.backgroundColor = [UIColor redColor];
  self.boolvalue = YES;
  NSLog(@"2");
  }
  return self;
}

- (void)loadView{
  NSLog(@"3");
  self.view = [UIView new];
  NSLog(@"4");
}

- (void)viewDidLoad {
  [super viewDidLoad];
  NSLog(@"5");
  if (self.boolvalue) {
  NSLog(@"6");
  }
  NSLog(@"7");
}
           

這裡執行的結果是:1、3、4、5、7、2。注意這裡不會執行6,因為那時還沒執行self.boolvalue=YES,而BOOL的預設值是false。

如果這裡把self.view.backgroundColor = [UIColor redColor];注釋掉,則執行的結果就是:1、2、3、4、5、6、7

可以去github上檢視Demo,喜歡的話star一下哦

github

CSDN