iOS基础-UIKit框架-多控制器管理-项目常用文件,4大对象,程序启动原理


一、项目常用文件及文件夹
1>Products文件夹:主要用来放Mac开发的可执行文件。对手机应用开发来说完全没用
2>Frameworks文件夹:当前开发依赖的一些框架和库。如Foundation框架,UIKit框架,CoreGraphics框架,test框架
3>工程名+Tests文件夹:用来做单元测试的,写好某一小块功能之后,可以在这里面写相应的代码来测试我写好的这个函数或者写好的这个功能是否正确
4>支持文件夹下的 工程名--info.plist文件 :是应用程序的一个配置文件,该文件对工程做一些运行期的配置,非常重要,不能删除
*项目中其他plist文件不能带有"Info"这个字眼,不然会被错认为是传说中非常重要的"Info.plist"。
*项目中含有一个InfoPlist.strings的文件,跟Info.plist文件的本地化相关
info.plist常见设置(这些都可以在工程文件左边栏第一个的General里可视化设置)
Bundle display name:显示在桌面上的应用的名称(若改名那么先删掉这个应用然后Clean一下,再运行。不然可能会有缓存,用的还是上次的plist文件)
Bundle identifier:程序的唯一标识(发布应用,真机调试,安装应用都会用到),如果有2个应用的程序标识一样,那么后安装的会覆盖前安装的程序。如cn.baidu
问:为什么域名要倒过来写?
答:因为域名是唯一的,如果百度和谷歌都开发地图,那么两个map就会有一个被覆盖。所以将域名倒过来写com.baidu.map,com.google.map就不会覆盖了。
Bundle version.string.short:苹果商店的正式版本(后一次一定要比前一次大)
Bundle version:内部版本
Main storyboard file base name:Main 那么以后就会加载Main.storyboard
plist文件通过xml保存,xml是用来保存数据的(通过字典键值对的形式保存)
5>支持文件夹下的 工程名--Prefix.pch文件(也是一个头文件)
*pch头文件的内容能被项目中的其他所有源文件共享和访问
用途:
A.一般在pch文件中定义一些全局的宏,或导入一些全局都能用到的头文件
B.用来自定义Log(不会这个就等于你没有开发经验)
在开发中分为两个阶段
1.开发调试阶段:是需要打印LOG调试程序的,如果程序处于调试阶段,系统会为我们定义一个名为DEBUG的宏
2.发布阶段:不需要打印LOG,因为LOG很占用资源并且用户看不懂LOG,如果程序处于发布阶段,系统就会自动删除名为DEBUG的宏
所以需要自定义LOG
*在pch文件中添加下列预处理指令(写在#ifdef __OBJC__和#endif之间),然后在项目中使用NJLog(...)来输出日志信息,就可以在发布应用的时候,一次性将NSLog语句移除(在调试模式下,才有定义DEBUG)
#ifdef DEBUG
#define NJLog(...)NSLog(__VA_ARG5__)//将自定义宏替换成系统宏
#else
#define NJLog(...) //表示这个自定义宏什么都不替换,所以之前所有用NJLog打印的语句都变成了空白。
#endif
//PS:三个点...代表可变参数

pch文件里默认代码的说明
//在所有的.m文件和.mm文件中默认就定义了__OBJC__这个宏,默认导入2个框架
#ifdef __OBJC__
//如果这个全局的头文件或者宏只需要在.m文件和.mm文件中使用,请把该头文件或宏写到#ifdef __OBJC__和#endif之间
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif

以后工作第一件事就是打开pch文件,查看公司自定义的LOG是什么,然后使用公司自定义的LOG,永远不要使用系统LOG。

二、4大对象

对象1:UIApplication
:

1.获取UIApplication

UIApplication *app = [UIApplication sharedApplication];
UIApplication *app1 = [UIApplication sharedApplication];
//app和app1的地址是相同的。证明只有一个UIApplication对象
//UIApplication *app2 = [UIApplication alloc] init];//这句会报错,因为只能有一个UIApplication对象,不能再创建


2.在View上添加一个按钮,当点击按钮时做应用级别的操作

UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100,100,100,100)];
[btn setTitle:@"点我啊" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(onClick) forControlEvents:UIControlEventTouchUpInside];
btn.backgroundColor = [UIColor redColor];
[self.view addSubview:btn];
-(void)onClick
{
UIApplication *app = [UIApplication sharedApplication];
//桌面图标左上角就会显示红色的998标签,代表有新的消息
app.applicationIconBadgeNumber = 998//状态栏上的小菊花(联网动画)
app.networkActivityIndicatorVisible = YES;
}


3.修改状态栏样式(设置状态栏是否隐藏同理)
方法一:通过控制器修改状态栏(适用于应用中包含多种样式状态栏的情况)

-(UIStatusBarStyle)preferredStatusBarStyle
{
   return UIStatusBarStyleLightContent;
}


方法二:通过UIApplication修改状态栏(适用于应用中状态栏样式不变的情况)
1>先在Info.Plist文件中添加一个属性View controller-based status bar appearance,并设置为NO
2>app.statusBarStyle = UIStatusBarStyleLightContent;
下面的方法还可以设置动画
[app setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

/*
URL:统一资源定位符,用来唯一地表示一个资源 
URL:协议头://主机地址/资源路径
网络资源:http://www.baidu.com/images/20140603/abc.png
本地资源:file://users/apple/desktop/abc.png
*/
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
[app  openURL:url];
//系统会自动判断资源类型并且使用适当应用打开


对象2:UIApplicationDelegate



对象3:UIWindow

#pragma mark - 代理方法
//当应用程序启动完毕的时候就会调用(系统自动调用,且只调用一次,退到后台再启动就不会再调用了)
-(BOOL)application:(UIApplication *)application  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
   return YES;
}
//即将失去活动状态的时候调用(失去焦点,不可交互)
-(void)applicationWillResignActive:(UIApplication *)application
{
}

//应用程序进入后台的时候调用
//一般在该方法中保存应用程序的数据,以及状态
-(void)applicationDidEnterBackground:(UIApplication *)application
{

}

//应用程序即将进入前台的时候调用
//一般在该方法中恢复应用程序的数据,以及状态
-(void)applicationWillEnterForeground:(UIApplication *)application
{

}

//重新获取焦点(能够和用户交互)
-(void)applicationDidBecomeActive:(UIApplication *)application
{

}

//应用程序即将被销毁的时候会调用该方法
//注意:如果应用程序处于挂起状态的时候无法调用该方法
-(void)applicationWillTerminate:(UIApplication *)application
{

}

//应用程序接收到内存警告的时候就会调用
//一般在该方法中释放掉不需要的内存
-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{

}

UIWindow的创建
系统会在didFinishLaunchingWithOptions:方法中自动创建UIWindow,设置其背景色为白色,并将UIWindow显示出来。
创建一个空Application就可以看到这些细节,但需要自己创建控制器(如果创建Single View Application就不需要,系统会自动创建)
方式一:将控制器view添加到UIWindow上
问题:当view发生一些事件的时候,通知控制器,但是控制器已经销毁了,所以可能出现未知错误
方式二:将Window的根控制器设置为创建的控制器
(建议使用这个方法,系统自动设置时也是这样做的。)
好处:当发生旋转事件的时候,UIApplication对象会将旋转事件传递给UIWindow,UIWindow又会将旋转事件传递给它的根控制器,由根控制器决定是否需要旋转,所以设置了根控制器就会旋转,方便用户操作。

对象4:UIViewController

三、程序启动原理
打开程序会执行main函数,由上至下执行以下代码

int main(int argc,char * argv[ ])
{
/* 了解即可
argc:系统或者用户传入的参数个数
argv:系统或者用户传入的实际参数
*/
return UIApplicationMain(argc,argv,nil,NSStringFromClass  ([NJAppDelegate class]));
/* 了解即可
1.根据传入的第三个参数创建UIApplication对象
2.根据传入的第四个参数创建UIApplication对象的代理
3.设置刚刚创建出来的代理对象为UIApplication的代理
4.开启一个事件循环(UIApplicationMain永远不会返回)
*/
}


iOS程序的启动过程(需要掌握)

监听系统事件,然后将事件队列(先进先出)里的事件依次处理,处理一个扔一个,有事件就处理,没事件就休息,相当于一个死循环,永远不返回。
两种情况会返回
1.被系统主动关掉
2.被用户主动关掉

笔记:

程序完整启动过程
1.main函数
|
2.UIApplicationMain(创建UIApplication及其代理,并设置代理)
|
3.没有storyboard的情况
delegate对象开始处理(监听)系统事件
*程序启动完璧的时候就会调用代理的application:didFinishLaunchingWithOptions:方法
*在application:didFinishLaunchingWithOptions:方法中创建UIWindow
*创建和设置UIWindow的rootViewController
*显示窗口
3.有storyboard的情况
根据Info.plist获得最主要storyboard的文件名,加载最主要的storyboard
*创建UIWindow
*创建和设置UIWindow的rootViewController
*显示窗口

问:为什么必须要有UIWindow才能显示内容?
答:因为只有UIWindow有makeKeyAndVisible(让窗口成为主窗口并显示出来)
PS:一个应用程序只能有一个主窗口(后一个会覆盖前一个)

BUG:iOS7和iOS8里面主窗口和次窗口没区别。

原文地址:https://www.cnblogs.com/marshall-yin/p/4726252.html