天天看点

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