从控制台输出Hello World是我学习C语言的第一步,也是我人生中非常重要的一步。多年后的今天,我希望仍以HelloWorld作为第一步,为大家开启一个神奇、瑰丽的世界——iOS。 本章以HelloWorld作为切入点,向大家系统介绍什么是iOS应用以及如何使用Xcode创建iOS应用。 2.1 创建基于nib的HelloWorld工程 在学习之初,我们有必要对使用Xcode创建iOS工程做一个整体概览,这里我们通过创建一个基于nib的HelloWorld iPhone应用来详述其中涉及的知识点。 实现HelloWorld应用后,会在界面上展示字符串Hello World(效果如图2-1所示),其中主要包含Label(标签)控件。 图2-1 HelloWorld的iPhone界面 2.1.1 创建工程 启动Xcode,然后点击File→New→Project菜单,在打开的Choose a template for your new project界面中选择Single View Application工程模板(如图2-2所示)。 图2-2 选择工程模板 接着点击Next按钮,随即出现图2-3所示的界面。 图2-3 新工程中的选项 这里我们可以按照提示并结合自己的实际情况和需要输入相关内容。下面简要说明图2-3中的选项。 Product Name。工程名字。 Organization Name。组织名字。 Company Identifier。公司标识(很重要)。一般情况下,这里输入的是公司的域名(如com.51work6),这类似于Java中的包命名。 Bundle Identifier。捆绑标识符(很重要)。该标识符由Product Name+ Company Identifier构成。因为在App Store发布应用的时候会用到它,所以它的命名不可重复。 Class Prefix。类的前缀。为生成的类加前缀(如XZYViewController)。 Devices。选择设备。可以构建基于iPhone或iPad的工程,也可以构建通用工程。通用工程是指一个工程在iPhone和iPad上都可以正常运行。 Use Storyboards。工程是否采用故事板技术。 Use Automatic Reference Counting。工程是否采用ARC(自动引用计数)技术。 Include Unit Tests。是否产生单元测试相关的类。 设置完相关的工程选项后,点击Next按钮,进入下一级界面。根据提示选择存放文件的位置,然后点击Create按钮,将出现如图2-4所示的界面。 图2-4 新创建的工程 在右下角的对象库中选择Label控件,将其拖曳到View上并调整其位置。双击Label控件,使其处于编辑状态(也可以通过控件的属性来设置),在其中输入Hello World,如图2-5所示。 图2-5 添加Label控件 至此,整个工程创建完毕。 点击图2-4左上角的Run按钮 ,即可看到运行结果。 我们在没有输入任何代码的情况下,就已经利用Xcode工具的Single View Application模板创建了一个工程,并成功运行,Xcode之强大可见一斑。 2.1.2 Xcode中的iOS工程模板 从图2-2中可以看出,iOS工程模板分为3类——Appliction、Framework & Library和Other,下面将分别详细介绍这3类模板。 1. Application类型 我们大部分的开发工作都是从使用Application类型模板创建iOS程序开始的。该类型共包含7个模板,具体如下所示。 Master-Detail Application。可以构建树形结构导航模式应用,生成的代码中包含了导航控制器和表视图控制器等。 OpenGL Game。可以构建基于OpenGL ES的游戏应用。 Page-Based Application。可以构建类似于电子书效果的应用,这是一种平铺导航。 Single View Application。可以构建简单的单个视图应用。 Tabbed Application。可以构建标签导航模式的应用,生成的代码中包含了标签控制器和标签栏等。 Utility Application。可以构建实用型应用程序,它会生成两个视图控制器——主视图控制器和子视图控制器。在iPhone中子视图以模态方式呈现,在iPad中子视图以浮动窗口(popover)的形式呈现。 Empty Application。可以构建一个空应用程序,需要我们自己添加视图等对象。该模板很少使用。 2. Framework & Library类型 Framework & Library类型的模板如图2-6所示,它可以构建基于Cocoa Touch的静态库。 图2-6 Framework & Library类型模板 说明 出于代码安全和多个工程重用代码的考虑,我们需要将一些类或者函数编写成静态库。静态库不能独立运行,编译成功时会生成名为libXXX.a的文件(例如libHelloWorld.a)。 3. Other类型 利用该类型,我们可以构建应用的内置付费内容包(In-App Purchase Content)和空工程,如图2-7所示。使用内置付费内容包,可以帮助我们构建具有内置收费功能的应用。 图2-7 Other类型模板 我们可以根据需要选用不同的工程模板,这可以大大减少我们的工作量。 2.1.3 应用剖析 在创建HelloWorld的过程中,生成了很多文件(展开Xcode左边的项目导航视图可以看到,如图2-8所示),它们各自的作用是什么?彼此间又是怎样的一种关系呢? 图2-8 项目导航视图 如图2-8所示,导航视图下有HelloWorld、Frameworks和Products三个组。 在HelloWorld组中共有两个类:AppDelegate和ViewController,以及一个组Supporting Files。 我们主要的编码工作就是在AppDelegate和ViewController这两个类中进行的,它们的类图如图2-9所示。 图2-9 HelloWorld工程中的类图 AppDelegate是应用程序委托对象,它继承了UIResponder类,并实现了UIApplicationDelegate委托协议。UIResponder类可以使子类AppDelegate具有处理相应事件的能力,而UIApplicationDelegate委托协议使AppDelegate能够成为应用程序委托对象,这种对象能够响应应用程序的生命周期。相应地,AppDelegate的子类也可以实现这两个功能。 ViewController类继承自UIViewController类,它是视图控制器类,在工程中扮演着根视图和用户事件控制类的角色。需要特别指出的是,ViewController.xib文件也是视图控制文件,起描述作用,与ViewController配套存在。 AppDelegate和ViewController类与main代码模块的主函数存在一种直接的调用关系,下面我们借助UML时序图来进行详细说明,如图2-10所示。 图2-10 HelloWorld启动时序图 可以看到,在HelloWorld启动过程中,首先调用main.m代码模块的main()主函数进行AppDelegate的实例化,具体代码如下所示: int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } AppDelegate类是应用程序委托对象,这个类中继承的一系列方法在应用生命周期的不同阶段会被回调。启动HelloWorld时,首先会调用application:didFinishLaunchingWithOptions:方法,该方法的代码如下: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]] autorelease]; self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; } 在该方法中,共做了3件事:实例化UIWindow,实例化ViewController,然后把ViewController作为根视图控制器放到UIWindow上。每一个iOS应用都有一个UIWindow对象,而每一个UIWindow对象上面都一个根视图,它所对应的控制器为根视图控制器(ViewController)。UIWindow对象与根视图UIView之间的关系如图2-11所示。在根视图上,我们可以添加子视图。各种控件(包括UIWindow)都继承了UIView。 图2-11 UIWindow对象与根视图 Supporting Files组共有4个文件。为了便于大家理解,经过分析和提炼,我们将各文件的作用以表的形式向大家总结说明,见表2-1。 表2-1 Supporting Files组文件说明表 文 件 名 说 明 HelloWorld-Info.plist 工程属性描述文件,它的命名必须是“工程名+Info.plist” InfoPlist.strings 工程本地化的字符串文件 main.m 应用程序的入口程序文件,它不是一个类,其中只有一个main()主函数,应用的运行都是由此开始 HelloWorld-Prefix.pch 在这个文件中可以引入一些头文件,这样工程中的其他文件就不需要再引入了。它的命名必须是“工程名+ Prefix.pch” Frameworks组包含工程里引用到的框架或类库,而Products组是工程将要生成的产品包。