工程的配置中Info选项里面的内容实际上是info.plist文件里面的内容的拷贝,info.plist里面存放了许多关于项目启动参数的配置信息。应该注意:若想往项目中添加自定义的plist文件,应该使文件名中不包含info。info.plist修改和其他的plist文件修改方式一样,都是键值对的修改。但是要注意的是当使用Source Code方式打开该文件的时候,键名和用plist方式打开时不一样。就xml源码文件讨论,键名分为以下几种:
Core Foundation Keys
该类的keys的特点是以CF为前缀,用以代表Core Foundation,描述了一些常用的行为项
Lanch Services Keys
加载服务项,提供了App加载所依赖的配置,描述了app启动的方式选择。
Cocoa Keys
Cocoa框架或Cocoa Touch框架依赖这些keys来标识更高级别的配置项目,如app的main
nib文件,主要类。这些key描述影响着Cocoa和Cocoa Touch框架初始化和运行app的运行方式
UIKit Keys
描述IOS Apps的行为,每个IOS应用都依赖于Info.
plist的keys来与IOS系统通信。Xcode提供了生成的plist文件提供了所有app所需的那些比较重要的keys。
但app可能需要扩展默认的plist来描述更多的信息,如定制app启动后的默认旋转方向,标识app是否支持文件共享等等。
OS X Keys
描述了Mac Apps的行为。
下面是一些常用的键的意义:
1.Localiztion native development region --- CFBundleDevelopmentRegion
本地化相关,如果?户所在地没有相应的语言资源,则用这个key的value来作为默认
2.Bundle display name --- CFBundleDisplayName
设置程序安装后显示的名称。应?程序名称限制在10-12个字符,如果超出,将被显示缩写名称。
3.Executaule dile -- CFBundleExecutable
程序安装包的名称
4.Bundle identidier --- CFBundleIdentidier
该束的唯一标识字符串,该字符串的格式类似 com.yourcompany.yourapp,如果使?用模拟器跑你的应用,这个字段没有用处,如果你需要把你的应?部署到设备上,你必须?成一个证书,?而在?生成证书的时候,在apple的?网站上需要增加相应的app IDs.这?有一个字段Bundle identidier,如果这个Bundle identidier是一个完整字符串,那么文件中的这个字段必须和后者完全相同,如果app IDs中的字段含有通配符*,那么文件中的字符串必须符合后者的描述。
5.InfoDictionary version --- CFBundleInfoDictionaryVersion Info.plist
格式的版本信息
6.Bundle name --- CFBundleName
产品名称
7.Bundle OS Type code -- CFBundlePackageType
?来标识束类型的四个字母长的代码
8.Bundle versions string, short --- CFBundleShortVersionString
?向用户市场的束的版本字符串
9.Bundle creator OS Type code --- CFBundleSignature
用来标识创建者的四个字母长的代码
10.Bundle version --- CFBundleVersion
应?程序版本号,每次部署应用程序的一个新版本时, 将会增加这个编号,在app store上用的。
11.Application require iPhone environment -- LSRequiresIPhoneOS
用于指示程序包是否只能运行在iPhone OS 系统上。Xcode自动加入这个键,并将它的值设置为true。您不应该改变这个键的值。
12.Main storybard dile base name -- UIMainStoryboardFile
这是一个字符串,指定应用程序主nib文件的名称。
13.supported interface orientations -- UISupportedInterfaceOrientations
程序默认支持的设备方向。
pch文件,是prefix header file。是程序运行起来后的全局头文件,当添加了该文件后,不用在其他文件中使用#include或者是#import导入该文件,就可以直接使用该文件中的各种内容,比如宏定义和常量和一些公用的类。在xcode5及之前可以直接使用pch文件,在xcode6之后需要在Build Settings中的Apple LLVM 6.0-Language项中的Prefix Header条目中,设置pch文件所在的目录为$(SRCROOT)/对应的文件夹名/PrefixHeader.pch,例如在根目录中 可以直接设置$(SRCROOT)/PrefixHeader.pch
当程序中的NSLog较多时,会造成很大的性能问题(NSLog是一个IO操作),对于发布程序是非常不好的,如果依次找到程序中的所有NSLog并将他们删除或者注释,工程项是巨大的,因此可以是用在pch中设置一个条件编译,如果是在调试状态下NSLog为正常的代码,如果在发布状态下则忽略他们。
class="prettyprint">#ifdef DEBUG #define NSLog(...); NSLog(__VA_ARGS__); #else #define NSLog(...); #endif
在调试状态下__VA_ARGS__的内容会替换为...中的内容(这是宏定义中提取方法参数中常用的方法),而在发布状态的时候,则直接忽略了NSLog(...)
ios开发中难免会遇到一些oc与c混编的时候,当使用了pch文件时,c文件是不会识别上面的条件编译和#import等指令的,这时候应该使用另外一个条件编译来避免出现问题:
#ifdef __OBJC__ #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> #endif-2.应用程序对象UIApplication介绍
UIApplication是一个单例类,可以做一些应用级别的操作
1.应用图标右上角的消息条数applicationIconBadgeNumber
2.联网操作时,状态栏上的等待图标指示器。waiting图标。networkActivityIndicatorVisible
3.利用UIApplication打开某个资源
** 打开一个网页:
[app openURL:[NSURL URLWithString:@"http://ios.icast.cn"]];
** 打电话
[app openURL:[NSURL URLWithString:@"tel://10086"]];
** 发短信
[app openURL:[NSURL URLWithString:@"sms://10086"]];
** 发邮件
[app openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]];
4.通过UIApplication管理状态栏:
iOS7开始可以通过两种方式来控制状态栏
1> 控制器- (BOOL)prefersStatusBarHidden
- (UIStatusBarStyle)preferredStatusBarStyle
2>.UIApplication
如果希望通过UIApplication来管理,步骤如下:
1> 在Info.plist文件中增加一个配置项
* View controller-based status bar appearance = NO,
2>然后编写如下代码:// 还可以用方法调用的形式,这样是可以设置动画的
app.statusBarHidden = YES; app.statusBarStyle-3.UIApplicationDelegate介绍,程序启动过程
在main函数中进行的设置UIApplication对象的代理。
App容易受到干扰。正在玩游戏,一个电话打过来了。
* 应用程序的生命周期事件(如程序启动和关闭)
* 系统事件(如来电)
* 内存警告
* … …
** 处理这些干扰事件,就要用到AppDelegate代理对象了。
** 总结: AppDelegate的主要作用就是处理(监听)应用程序本身的各种事件:
* 应用程序启动完毕
* 应用程序进入后台
* 应用程序进入前台
* 内存警告
* 等等, 都是应用程序自身的一些事件
** 要想成为UIApplication的代理对象, 必须遵守:UIApplicationDelegate协议。
** 代理中的若干方法介绍:
1. - (BOOL)application: didFinishLaunchingWithOptions:
// app第一次启动完毕后就会调用(当程序启动后会显示一张启动图片, 当这个图片显示完毕, 消失后, 就开始调用这个方法)
2. - (void)applicationDidEnterBackground:(UIApplication *)application
// 当程序进入后台时, 调用该方法。(比如:按了Home键, 或者一个电话打过来了, 当前程序都会进入后台。)
// 在这个方法中可以做一些保存当前程序数据, 暂停程序的操作。
3. - (void)applicationWillEnterForeground:(UIApplication *)application
// 当程序再次进入前台的时候调用。
4. - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
// 当发生内存警告时触发该事件。
程序启动后:
didFinishLaunchingWithOptions-->applicationDidBecomeActive
按home键使程序进入后台:applicationWillResignActive--->applicationDidEnterBackground
让程序会到主界面:applicationWillEnterForeground--->applicationDidBecomeActive
在主界面时让程序退出:applicationDidEnterBackground--->applicationWillTerminate
在后台时退出:applicationWillTerminate
-4.UIWindow
** UIWindow是一种特殊的UIView, UIWindow也是继承自UIView。
** 通常一个app只会有一个UIWindow对象。
** iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了
** 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow
** 在文档中找: Cocoa Touch Layer -> UIKit -> Guides -> View Controller Programming Guide for iOS -> View Controller Basics -> 关于UIWindow与控制器View的关系图片。
** 创建过程UIWindow -> UIViewController -> UIView -> 把UIView加到UIWindow对象中。
-5.程序界面显示出来的过程
当配置了启动的时候使用main.storyboard的时候, 此时, 当程序启动完毕后, 会自动创建UIWindow, 然后再根据main.storyboard文件创建对应的控制器, 以及控制器中的view. 然后把控制器的View添加到UIWindow上.然后我们就看到界面了.
如果没有为项目配置启动的时候使用哪个storyboard, 那么应用程序启动完毕以后不会创建UIWindow对象, 以及对应的控制器等等.这时就需要自己去创建
在app代理类的FinishLaunching中
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 创建一个控制器, 然后把控制器设置给UIWidnow MKViewController *mkViewCotroller = [[MKViewController alloc] init]; // 设置hmVc为self.window的根控制器 self.window.rootViewController = mkViewCotroller; // 把这个(self.window)设置为主窗口, 并且显示出来 [self.window makeKeyAndVisible];
需要注意的是:
不要直接把控件添加到UIWindow上, 而是要现创建控制器, 然后向控制器所管理的view中添加子控件, 然后把控制器设置给UIWindow.
原因:
1> UIWindow一直会存在, 直到应用程序退出.所有加到UIWindow中的子控件也就一直会被UIWindow强引用.
2> 如果直接把子控件加到UIWindow中, 那么所有子控件的事件都需要让应用程序代理来监听.
实际是应该让对应的控制器来监听这些事件.
3> 当屏幕旋转的时候, UIWindow监听到了这个旋转事件, 然后把它传递给控制器, 控制器再让对应的子控件做旋转.如果要是直接向UIWindow中添加子控件, 那么就没有控制器, 子控件无法监听旋转事件.
-6.总结程序启动完整过程
(有storyboard和没有storyboard的分别总结)