首页 第3章 创建你的第一个iPhone应用程序

第3章 创建你的第一个iPhone应用程序

举报
开通vip

第3章 创建你的第一个iPhone应用程序 第 3章 创建你的第一个 iPhone应用程序 本章将介绍如何创建一个简单的 iPhone 应用程序。本文不打算对 iPhone 目前可用的特性作全面介 绍,而是介绍一些基础的技术,但这些基础技术,不要求你现在一定掌握,如果你不明白,可以跳过, 继续进行下面的,你只管根据本章的介绍进行“照葫芦画瓢”就可以可以,这样目的是,使你对基础开 发过程有初步了解,窥视一下开发 iPhone 程序的神秘色彩,打破对开发 iPhone 程序的那种畏惧感。这 也是介绍本章的最重要的目的。 注意:为了...

第3章  创建你的第一个iPhone应用程序
第 3章 创建你的第一个 iPhone应用程序 本章将介绍如何创建一个简单的 iPhone 应用程序。本文不打算对 iPhone 目前可用的特性作全面介 绍,而是介绍一些基础的技术,但这些基础技术,不要求你现在一定掌握,如果你不明白,可以跳过, 继续进行下面的,你只管根据本章的介绍进行“照葫芦画瓢”就可以可以,这样目的是,使你对基础开 发过程有初步了解,窥视一下开发 iPhone 程序的神秘色彩,打破对开发 iPhone 程序的那种畏惧感。这 也是介绍本章的最重要的目的。 注意:为了学习本本章,需要安装 iPhone SDK和开发者工具,它们位于 iPhone开发中心。文档描 述的工具包含在 iPhone SDK v3.0里面—请检查一下 Xcode版本,它不能低于 3.1.3。 3.1 示例实现目标 在学习过程中,将创建一个很简单的应用程序。它含有一个文本字段,一个标签和一个按键。可以 把名字输入到文本字段中,再按下按键,这时标签的文本就会变成 “Hello, !”。如图 3-1 所 示。 图 3-1 程序运行效果 尽管这是个很简单的应用程序,但它介绍了基本的设计模式、工具、以及利用 Cocoa Touch 进行 iPhone 开发的基础技术。 Cocoa Touch 包括 UIKit 和 Foundation 这两个框架。当在 iPhne OS 上开发事 件驱动的图形化应用程序时,需要使用它们提供的工具和基本结构。同时,Cocoa Touch 还包含其他几 个框架,它们提供一些基本的服务,可用于访问设备的特色内容,例如访问用户的联系人。 3.2 应用概念概述 在介绍创建之前,先初步了解一下在创建中应用的一些基本概念,它们主要有设计模式、委托、模 型——视图控制器和目标——动作等,了解这些概念将有助于理解后面创建机制。这些概念,将是以后 在 iPhone/iPad 开发中经常用到的一些应该概念。基于篇幅的限制,这里只简单的介绍一下,如果想更 进一步的了解,建议找专门介绍这些方面的书籍。 3.2.1 设计模式 设计模式是一种设计 模板 个人简介word模板免费下载关于员工迟到处罚通告模板康奈尔office模板下载康奈尔 笔记本 模板 下载软件方案模板免费下载 ,用于解决在特定环境中反复出现的一般性的问题。它是一种抽象工具, 在架构、工程、和软件开发领域相当有用。下面的部分将概要说明什么是设计模式,解释为什么设计模 式在面向对象的设计中非常重要,并讨论一个设计模式的实例。 3.2.2 委托 委托模式是一个对象周期性地向被指定为其委托的另一个对象发送消息,向其请求输入或者通知某 件事情正在发生。该模式可替换类继承来对可复用对象的功能进行扩展。 在本文将要创建的应用程序中,应用程序对象会向其委托发送消息,通知它主要的启动例程已经完 成并且定制的配置可开始执行。为了建立并管理视图,委托会创建一个控制器实例。另外,当用户点击 Return 按键后,文本字段也会通知它的委托(即所创建的控制器对象)。 委托方法通常会集中在一起形成一份协议。 一份协议基本上就是一个方法的列 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 。如果一个类遵 循某个协议,则它要保证实现协议所要求的方法(有些方法可选择实现与否)。委托协议规定了一个对 象可以发送给委托的所有消息。 委托是一种对象,当向外委托任务的对象遇到程序中的事件时,它的委托可以代表它对事件进行处 理,或者和它进行协调。向外委托任务的对象通常是一个响应者对象—即继承自 NSResponder 的对象— 负责响应用户事件。委托则是受托进行事件的用户界面控制,或者至少根据应用程序的具体需要对事件 进行解释的对象。 为了更好地理解委托的价值,让我们考虑一个复活的 Cocoa 对象,比如一个窗口(NSWindow 的实 例)或者表视图(NSTableView 的实例)。这些对象的设计目的是以一般的方式实现一个具体的角色; 举例来说,窗口对象负责响应窗口控件的鼠标操作,处理象关闭窗口、调整尺寸、以及移动窗口的位置 这样的事件;这个受限而又具有一般性的行为必然限制该对象认识一个事件对应用程序其它地方的影 响,特别是当被影响的行为只存在于 的应用程序的时候。委托为 的定制对象提供一种方法,使它可以 就应用程序特有的行为和复活对象进行通讯。 委托的编程机制使对象有机会对自己的外观和状态、以及程序在其它地方发生的变化进行协调,这 些变化通常是由用户动作触发的。更重要的是,委托使一个对象有可能在没有进行继承的情况下改变另 一个对象的行为。委托几乎总是 的一个定制对象,它通过定义将应用程序具体逻辑结合到程序中,而 这些逻辑是具有一般性的,是向外委托任务的对象自身不可能知道的。 委托是如何工作的 委托机制的设计是很简单的(图 5-2)。希望向外委托任务的类需要有一个插座变量,通常命名为 delegate,并包含对该插座变量进行设置和访问的方法。它还需要声明一或多个方法,构成一个非正式 的协议,但不进行实现。非正式协议通常是希望向外委托任务的类的一个范畴,和正式协议的不同之处 在于,它不需要实现协议中的所有方法。在非正式协议中,委托只实现希望进行协调或对缺省行为实施 影响的方法。 图 5-2 委托的机制 非正式协议的方法标记着进行任务委托的对象需要处理或预期发生的重大事件。该对象希望就这些 事件和委托进行交流,或者就即将发生的事件向委托请求输入或批准。举例来说,当用户点击一个窗口 的关闭按键时,窗口对象会向委托发送 windowShouldClose:消息;这就使委托有机会否决或推迟窗口的 关闭,如果必须保存窗口关联数据的话(参见图 5-3)。 图 5-3 一个更接近现实的、涉及委托的序列 3.2.3 模型-视图控制器 模型-视图-控制器模式(MVC)是一个相当老的设计模式,它的一些变体至少在 Smarttalk 的早 期就出现了。它是一种高级别的模式,关注的是应用程序的全局架构,并根据各种对象在程序中发 挥的作用对其进行分类。它也是个复合的模式,因为它是由几个更加基本的模式组成的。 模型对象表示数据。例如,在一款游戏中,SpaceShips 和 Rockets 是模型对象,在一个用于生产的 应用中,ToDo 项和 Contacts 是模型对象,在一个绘画应用中,Circles 或 Squares 是模型对象。 视图对象知道如何显示数据(模型),并且它们有可能会允许用户对数据进行编辑。在本文将要创 建的应用程序中, 需要一个主视图来包含其它几个视图— 一个文本字段,它用于捕获用户输入信息; 第二个文本字段,它用于显示文本,而文本内容则是基于用户的输入;另外还需要一个按键,用户利用 它来告知我们第二个文本字段应该被更新。 控制器对象位于模型和视图之间。面向对象的程序在设计上采用 MVC 模式会带来几个方面的好处。 这种程序中的很多对象可能更具重用性,它们的接口也可能定义得更加良好。程序从总体上更加适应需 求的改变—换句话说,它们比不基于 MVC 的程序更加容易扩展。而且,Cocoa 中的很多技术和架构— 比如绑定技术、文档架构、和脚本技术—都基于 MVC,而且要求定制对象充当 MVC 定义的某种角色。 1. 模型对象负责包装数据和基本行为 模型对象代表特别的知识和专业技能,它们负责保有应用程序的数据和定义操作数据的逻辑。一个 定义良好的 MVC 应用程序会将所有重要的数据封装在模型对象中。任何代表应用程序留存状态的数据 (无论该状态存储在文件中,还是存储在数据库中),一旦载入应用程序,就应该驻留在模型对象中。 因为它们代表与特定问题域有关的知识和专业技能,所以有可能被重用。 在理想情况下,模型对象不和负责表示与编辑模型数据的用户界面建立显式的连接。举例来说,如 果有个代表一个人的模型对象(假定 在编写一个地址本), 可能希望存储这个人的生日,则将生日存 储在 的 Person 模型对象是比较好的做法。但是,日期格式字符串或其它有关日期如何表示的信息可能 存储在别的地方比较好。 在实践上,这种分隔并不总是最好的,这里有一定的灵活空间。但一般来说,模型对象不应该关心 界面和表示的问题。一个具有合理例外的例子是描画程序,它的模型对象代表要显示的图形。图形对象 知道如何描画自身是合理的,因为它们存在的主要原因就是为了定义视觉上的信息。但是即使在这种情 况下,图形对象也不应该完全依赖于特定的视图,它们不应该负责描画的具体位置,而应该由希望表示 这些图形对象的视图对象发出描画的请求。 2. 视图对象负责向用户表示信息 视图对象知道如何显示应用程序的模型数据,而且可能允许用户对其进行编辑。视图对象不应该负 责存储它所显示的数据(这当然不是说视图永远不存储它所显示的数据。由于性能上的原因,视图可能 对数据进行缓存,或使用类似的技巧)。一个视图对象可能负责显示模型对象的一部分或全部,甚至是 很多不同的模型对象。视图对象可能有很多变化。 视图对象应该尽可能可重用和可配置,它们可以在不同的应用程序中提供一致的显示。在 Cocoa 中, Application Kit 定义了大量的视图对象,其中很多对象都出现在 Interface Builder 的选盘上。 可以通过重 用 Application Kit 的视图对象,比如 NSButton 对象,来保证应用程序中的按键和其它 Cocoa 应用程序的 按键行为是一样的,从而保证不同的应用程序在外观和行为上具有高度的一致性。 视图必须正确地显示模型,因此需要知道模型发生的改变。由于模型对象不应该依赖于特定的视图 对象,所以需要有一个一般性的方式来指示模型对象发生了变化。 3. 控制器对象连接模型和视图 控制器对象是应用程序的视图对象和模型对象之间的协调者。通常情况下,它们负责保证视图可以 访问其显示的模型,并充当交流的管道,使视图可以了解模型发生的变化。控制器对象也可以为应用程 序执行配置和协调的任务,管理其它对象的生命周期。 在一个典型的 Cocoa MVC 设计中,当用户通过某个视图对象输入一个值或做出一个选择时,该值 或选择会传递给控制器对象。控制器对象可能以应用程序特有的方式对用户输入进行解释,然后或者告 诉模型对象如何处理这个输入—比如“增加一个新值”或“删除当前记录”,或者使模型对象在其某个 属性上反应被改变的值。基于同样的用户输入,一些控制器对象也可以通知相应的视图对象改变其外观 或行为的某个部分,比如禁用某个按键。反过来,当一个模型对象发生变化了—比如加入一个新的数据 源—模型对象通常将变化通知控制器对象,由控制器对象要求一或多个视图对象进行相应的更新。 控制器对象可能是可重用的,也可能是不可重用的,取决于它们的一般类型。"Cocoa 控制器对象的 类型"部分描述 Cocoa 中不同类型的控制器对象。 3.2.4 目标-动作 1. 目标 目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参见"插座变量" 部分)的形式保有其动作消息的目标。虽然目标可以是任何实现恰当的动作方法的 Cocoa 对象,但通常 是 的定制类的一个实例。 2. 动作 动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现的方法。控件, 或者更为常见的是它的单元,将动作存储为 SEL 类型的实例变量。SEL 是一种 Objective-C 的数据类型, 用于指定消息的签名。动作消息必须有一个简单而清楚的签名,消息调用的方法没有返回值,且只有一 个类型为 id 的参数。该参数约定的名称为 sender。 委托、绑定、和通告机制在处理程序中特定形式的对象间通讯是很有用的。但是,对于大多数可视 的通讯形式,它们并不特别合适。一个典型应用程序的用户界面是由一些图形对象组成的,最常见的对 象可能就是控件。控件是真实世界或逻辑设备的对等物(比如按键,滑块,检查框等)。和真实世界中 的控制接口(比如收音机调谐器)一样, 可以用控件来传达 对其所在系统的控制意图-在这里,系统 是一个应用程序。 3. 目标-动作机制 用户界面中的控件的作用很简单:它对用户的意图进行解释,并指示其它对象执行相应的请求。当 用户对控件进行动作,比如点击控件或按下回车键,硬件设备就会产生一个未经加工的事件。控件接受 该事件(在根据 Cocoa 的需要进行恰当的封装之后),并将它翻译为应用程序的具体指令。然而,事件 的本身并没有给出很多关于用户意图的信息,它们只是告诉 用户点击了鼠标键,或者按下了一个按键。 因此,程序需要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制。 Cocoa 通过目标-动作机制来实现控件和对象的通讯。这个机制使控件和它的单元(可能有多个)可 以把向恰当对象发送应用程序具体指令所需要的信息封装起来。接受对象-通常是个定制类的实例-被 称为目标(target)。动作是控件发送给目标的消息(action)。对用户事件感兴趣的对象-即目标-也 就是为用户事件给出意义的对象,这个意义通常在动作的名称中反应出来。 目标-动作机制允许一个控件对象(诸如按键或滑动条) 向另外一个对象发送一条消息(即动作), 以之作为对某个用户事件(例如一个点击事件或者一个敲击事件)的响应。接收到消息的对象则可以对 消息进行解释,并将其作为一个特定于应用程序的指令进行处理。 3.3 教你如何创建工程 在本节,将要使用 Xcode 创建前面所说的工程,同时还将查明应用程序的启动过程。 3.3.1 使用 Xcode 主要利用 Xcode 来创建 iPhone 应用程序,它是苹果的 IDE(集成开发环境)。 也可以利用它来创建 各种不同类型的工程,包括 Cocoa 以及命令行工具,这些知识,在前面的章节中已经介绍过,本节的重 点是如何使用 XCode。 (1) 启动 Xcode(缺省情况下,Xcode 位于 /Developer/Applictions 里面),然后请选择 File > New Project,这样就可以创建一个新工程。 应该会看到一个新的窗口,如图 5-4 所示。 图 5-4 创建新工程 注意: 如果 没有看到 “Use Core Data for storage”这一选项,则请 务必 安装 iPhone OS SDK 3.0版本— 应该安装 Xcode3.1.3或者更高的版本。 (2)请选中 Window-Based Application 并点击 Choose 按键。 (请不要勾选“Use Core Data for storage”,本例不使用 Core Data 机制。) 完成上述步骤后,屏幕会出现一张表格。请在上面选择工程的存储位置。 (3)请选择一个合适的位置(例如 可以放在桌面也可以放在一个定制的工程目录),然后为工程 添加一个名称—HelloWorld—再点击保存按键。 注意:在后续章节中,我们假定 将工程命名为 HelloWorld,因此应用程序的委托类就叫做 HelloWorldAppDelegate。如果使用其他名称,则应用程序委托类的名称将为 YourProjectNameAppDelegate。 完成上述步骤后, 将看到如下的新工程窗口,如图 5-5 所示。 图 5-5 新工程窗口 如果以前未曾用过 Xcode,则请花点时间来研究下该应用。请阅读 Xcode 工作空间 指南 验证指南下载验证指南下载验证指南下载星度指南下载审查指南PDF ,它可以帮 助 理解工程窗口的组织方式以及如何执行诸如编辑和保存文件这样的基本任务。现在, 可以链编并运 行程序,这样就能看到模拟器的外观。 (4)请选择 Build > Build and Go (Run)或者点击工具栏中的 Build and Go 按键。 iPhone 模拟器应该会自动启动。当 的应用程序启动后, 只看到一个白色屏幕。如希望了解白色的 屏幕从何而来,则 需先了解应用程序如何启动。 (5)退出模拟器。 3.3.2 应用程序引导 创建的模板工程已设置了基本的应用程序环境。它创建一个应用程序对象,将应用程序和窗口服务 器连接起来,建立一个运行循环以及其他等等。大部分的工作通过 UIApplicationMain 函数完成,如图 5-6 。 图 5-6 应用程序引导 main.m 文件中的 main 函数会调用 UIApplicationMain 函数: int retVal = UIApplicationMain(argc, argv, nil, nil); 该函数将会创建一个 UIApplicaion 类的实例。同时它会搜索应用程序的 Info.plist 属性列表文件。 Info.plist 文件是一部字典,它包含诸如应用程序名称、图标这样的信息。它也可以包含应用程序对象应 该加载的 nib 文件的名称,该名称由 NSMainNibFile 键指定。Nib 文件含有一份用户接口元素及其他对 象的档案— 将在后续章节进一步了解 Nib 文件的知识。本工程的 Info.plist 文件具有下面的内容: NSMainNibFile MainWindow 这表明应用程序启动时将会加载 MainWindow nib 文件。 如希望查看 nib 文件,请双击工程窗口 Resource group 中的 MainWindow.xib 文件。(虽然该文件 的扩展名为“xib”,但是习惯称之为“nib 文件”)。Interface Builder 将会启动并打开该文件,如图 5-7。 图 5-7 interface Builder Interface Builder 文档包含四个对象:  一个 文件拥有者代理对象。实际上,文件拥有者对象是 UIApplication 实例— 将在“文件拥有者”一节讨论该对象。  一个 第一响应者代理对象。  一个 HelloWorldAppDelegate 的实例,它会被设置成应用程序的委托。  一个窗口。它被设置为白色背景、启动时可见。应用程序启动时, 看到的窗口就 是它。 应用程序完成启动后,可以执行附加定制。图 5-8 描述的是一种通用模式,对于这种通用模式,将 会在下一节使用它。 图 5-8 一种通用模式 应用程序对象在完成启动后会向委托发送 applicationDidFinishLaunching:消息。通常情况下,委托不 是自己配置用户接口,而是创建一个视图控制器对象(一种特定的控制器,它负责管理一个视图—遵循 “模型-视图-控制器”描述的模型-视图-控制器设计模式)。然后委托向视图控制器请求视图(这个视 图由视图控制器根据要求创建),并将其添加成窗口的子视图。 3.4 如何添加一个视图控制器 在本章的示例程序中,需要使用两个类。一个是 Xcode 的应用程序模板提供的应用程序委托,程序 在 nib 文件中创建了一个该类的实例。另一个是需要您实现视图控制器类,将创建该类的一个实例。 3.4.1 添加一个视图控制器类 在大部分 iPhone 应用程序中,视图控制器起着核心作用。正如其名称所示,它负责管理一个视图。 在 iPhone 上,它们也帮助进行导航和内存管理。虽然本节例子程序不使用后两种功能,但对此有所了解 很重要。UIKit 提供一个特别的类 — 即 UIViewController 类—它封装了视图控制器应该具有的大部分 缺省行为。 应从它派生子类,在子类中定制应用程序的行为。 (1) 请选中 Xcode 项目管理器里的工程(即 HelloWorld 项目,位于 Groups and Files 列表的顶部) 或者选中 Classes 文件夹 — 新文件会被加入到当前选择的位置。 (2)请选择 File > New File。在 New File 窗口中,请选择 Cocoa Touch Classes,然后选择 UIViewController subclass,如图 5-9。同时,请勾选 Options 区域中标题为 With XIB for user interface 的 选择框。 图 5-9 创建新文件 注意: 如果 没有看到“With XIB for user interface”选项,请确保 安装 iPhone OS SDK 3.0 版 本- 应该安装 Xcode3.1.3或者更高的版本。 选中 “With XIB for user interface”表明 Xcode 在创建视图控制器的同时,会为其创建一份 nib 文 件,并将该文件添加到工程。(将在下一章详细讨论 Nib 文件。) (3)请点击 Next,在其后出现的屏幕中为文件起个名字,例如 MyViewController。(类名称习惯 以一个大写字母开头)。请务必创建.m 和.h 文件,并将二者都添加到工程,如图 5-10 所示。 图 5-10 MyViewController (4)请点击 Finish,文件会被添加到工程。 看一下新建的源文件, 会发现 Xcode 已经为 提供了各种方法的存根实现。目前无需追究这些方法 的具体含义。接下来,我们将创建一个控制器类的实例。 3.4.2 添加一个视图控制器属性 需确保在应用程序生存期间,视图控制器始终存在。将视图控制器作为应用程序委托的一个实例变 量是解决该问题的一个明智的方法。 添加到应用程序委托的实例变量是 MyViewController 类的实例。如果 声明了变量但未告知编译器 MyViewController 类的相关信息,编译器就会 报告 软件系统测试报告下载sgs报告如何下载关于路面塌陷情况报告535n,sgs报告怎么下载竣工报告下载 错误。通过导入头文件可以解决该问题,但在 Cocoa 中,通常 应该使用一个前向声明(forward declaration)—它向编译器承诺 MyViewController 类将在其 他地方定义,因此编译器现在无需耗时来对其执行检查。(如两个类需相互引用,则前向声明可以避免 环状包含,即两个头文件互相包含。)然后,请将 MyViewController 类的头文件导入到应用程序委托的 实现文件。 (1)请在应用程序委托头文件(HelloWorldAppDelegate.h)的接口声明前面-即 HelloWorldAppDelegate 声明前面-添加前向声明: @class MyViewController; (2)请在头文件大括号之间添加下面的代码,这是为了向应用程序委托添加一个实例变量: MyViewController *myViewController; (3)请在大括号之后 @end 之前添加下面的属性声明: @property (nonatomic, retain) MyViewController *myViewController; 基本上,上述声明指定:HelloWorldAppDelegate 实例含有一个属性, 可以使用 getter 和 setter 方法 —即 myViewController 和 setMyViewController:方法—来访问该属性,同时,委托实例还会保持该属性 (将在后续章节详细讨论保持)。 为确保正确,请确认 HelloWorldAppDelegate 类的接口文件(即 HelloWorldAppDelegate.h 文件)如下 所示(不显示注释): #import @class MyViewController; @interface HelloWorldAppDelegate : NSObject { UIWindow *window; MyViewController *myViewController; } @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) MyViewController *myViewController; @end 现在 可以开始创建视图控制器的实例。 3.4.3 创建视图控制器实例 已经把视图控制器属性添加到应用程序的委托,现在需要实际创建一个视图控制器实例,并将其设 置为属性的值。 请在应用程序委托类实现文件(即 HelloWorldAppDelegate.m 文件)中的 applicationDidFinishLaunching:方法开头添加如下代码,这些代码用于创建一个 MyViewController 实例: MyViewController *aViewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]]; [self setMyViewController:aViewController]; [aViewController release]; 虽然只有三行,但其中含意很多。这些代码作用如下:  创建并初始化一个视图控制器类的实例。  使用存取方法将新建的视图控制器是设置为 myViewController 实例变量值。 记住:未单独声明 setMyViewController:方法,而是隐式将其作为属性声明的一部分。  依照内存管理规则释放视图控制器。 先使用 alloc 方法创建一个视图控制器,然后用 initWithNibName:bundle:方法对其进行初始化。init 方法先指定控制器应加载的 nib 文件,然后指定在哪个程序包中可找到该文件。程序包是文件系统某个 位置的抽象,该位置存放了应用程序将会用到的代码和资源。相比自行定位文件系统的资源文件,使用 程序包有很多优势。它为我们提供了方便而简单的 API—bundle 对象仅通过名称就可以定位某个资源— 甚至连名称的本地化的工作,它也为 考虑了。 本章约定应该拥有任何通过 alloc 方法创建的对象(请参考内存管理规则了解其他约定)。因此, 还 需要:  放弃对所创建的对象的拥有权。  通常只在初始化函数中调用存取方法来设置实例变量。 上述代码第二行使用存取方法来设置实例变量,第三行调用 release 方法以放弃对所创建对象的拥有 权。 也可以使用其他方式来完成这些功能。例如,可以把这三行代码替换成下面两行: MyViewController *aViewController = [[[MyViewController alloc] initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]] autorelease]; [self setMyViewController:aViewController]; 该版本使用 autorelease 来放弃对新建视图控制器的所有权。不过此种方式中,放弃所有权的动作将 在未来的某一时刻执行。如果不理解此代码的含义,则请阅读 Cocoa 内存管理变成指南中 Autorelease Pools 一章。通常情况下,请尽可能地避免使用 autorelease 方法,因为相对于 release 方法来说,它是一 种资源密集型操作。 也可以将最后一行替换如下: self.myViewController = aViewController; 此处点号就是调用存取方法(即 setMyViewController:),这与前述实现调用的方法并无不同。点号 确实提供一种更为紧凑的语法—特别是在使用嵌套表达式的时候。将几个属性合在一起使用时,点号语 法能带来一些附加好处,但到底选择哪种语法,则很大程度上取决于个人的偏好。 3.4.4 如何建立视图 视图控制器负责管理和配置视图。 并不直接创建窗口的内容视图,而是从视图控制器获取,并将 其添加成窗口子视图。 释放视图控制器后,请添加如下的代码: UIView *controllersView = [myViewController view]; [window addSubview:controllersView]; 也可以使用一行代码来完成上面代码的功能: [window addSubview:[myViewController view]]; 但是将代码分为两行有助于强调内存管理的一个规则,它和我们之前看到的相反。由于并未使用 Cocoa 内存管理编程指南中的内存管理规则里所列出的方法来创建控制器视图,所以并不拥有该视图。 因此,把返回的对象传给窗口后,无需再对其作后续处理(即不用释放这个对象)。最后一行来自于 IDE 提供的模板: [window makeKeyAndVisible]; 这行代码会让窗口-现已含有 的视图-显示在屏幕上。之所以在窗口显示之前把视图添加进去, 是为了防止用户在实际内容显示前看到短暂的白屏。 3.4.5 内务处理做些什么 还剩几个任务:导入视图控制器头文件,合成存取方法,在 dealloc 方法中释放视图控制器(遵循 内存管理规则里面的规定)。 请在应用程序委托类的实现文件(即 HelloWorldAppDelegate.m)中执行下述操作:  请在文件的顶部导入 MyViewController 的头文件: #import "MyViewController.h"  请在类的 @implementation 代码块中通知编译器为视图控制器合成存取方法: @synthesize myViewController;  请在 dealloc 方法起始处释放视图控制器: [myViewController release]; 3.4.6 实现源码列表 为确保正确,请确定 的 HelloWorldAppDelegate 类的实现(即 HelloWorldAppDelegate.m 文件)如下所 示: #import "MyViewController.h" #import "HelloWorldAppDelegate.h" @implementation HelloWorldAppDelegate @synthesize window; @synthesize myViewController; - (void)applicationDidFinishLaunching:(UIApplication *)application { MyViewController *aViewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]]; [self setMyViewController:aViewController]; [aViewController release]; UIView *controllersView = [myViewController view]; [window addSubview:controllersView]; [window makeKeyAndVisible]; } - (void)dealloc { [myViewController release]; [window release]; [super dealloc]; } @end 3.4.7 测试你的应用程序 现在可以测试应用程序。 编译并运行工程(即点击 Build > Build and Run,或者点击 Xcode 工具栏的 Build and Run 按键)。 应用程序应能通过编译,不会报告错误。然后将在模拟器中再一次看到白色的屏幕。 3.5 查看 Nib 文件 Interface Builder 用于创建并配置 nib 文件。本节描述两个重要的概念:插座变量(outlet)以及文件 拥有者代理对象。 3.5.1 使用 Interface Builder Interface Builder 用于创建并配置 nib 文件,需使用 Interface Builder 创建用户接口。Interface Builder 并不生成源码,而是让 直接操作对象,并将这些对象保存在一份被称为 nib 文件的档案。 术语: 虽然 Interface Builder 文档的扩展名可能是“.xib” ,但历史上,其扩展名是“.nib”(“NextStep Interface Builder”的首字母缩写),因此人们就俗称其为“Nib 文件”。 程序运行时会加载 nib 文件,解档文件中的对象并且将其恢复到被保存至文件那一瞬间的状态-包括 对象间的所有关联。 3.5.2 Nib文件包含些什么 请双击 Xcode 中视图控制器的 XIB 文件(即 MyViewController.xib 文件),Interface Builder 会为 打开 该文件,如图 3-11。 图 3-11 NIB 文件 文件包含三个对象,文件拥有者代理,第一响应者代理以及一个视图。视图和 XIB 文件窗口分开显 示,以便于 对视图进行编辑。 3.5.3 文件的拥有者 Interface Builder 文档中的文件拥有者对象和添加进去的其他对象不同。它不是在加载 nib 文件的时 候创建,并且它会被设置为用户接口的拥有者—通常情况下,用户接口拥有者负责加载接口。如果 需 更加详尽的资料,请参看资源编程指南。在 的应用程序中,文件的拥有者是 MyViewController 的实例。 Interface Builder 需要知道文件拥有者是什么类型的对象,这样它才能让 在文件拥有者和其他对象 之间建立恰当的关联。 可以利用 Identity Inspector 来告诉 Interface Builder 该对象所属的类。实际上, 当 nib 文件伴随着视图控制器类一同被创建出来时,nib 文件中的文件拥有者的类型就已被设置完成。不 过现在,了解一下查看器对有很大好处。 请在 Interface Builder 文档的窗口中选择文件拥有者的图标,然后选择 Tools > Identity Inspector , 这样 Identity inspect 就会显示出来,如图 3-12 所示。 图 3-12 myViewController 属性 Class Identity 中的 Class 字段的值应该是 MyViewController。该值只是向 Interface Builder 承诺文件 拥有者是该类的实例,把该字段设置成某个类并不能保证文件拥有者就是所设的类的实例。文件拥有者 的类型取决于加载 nib 文件的时 所设置的对象。如果它是其他类的实例,则 nib 文件中建立的关联就无 法正确建立。 3.5.4 如何使用视图插座变量 可以使用查看器面板来查看-建立或打断-一个对象的关联。 请在 Interface Builder 文档窗口中按住 Control 键并点击文件拥有者,这样就可以在屏幕中显示一个 半透明的面板,面板里显示了文件拥有者的关联,如图 3-13 所示。 图 3-13 插座变量的使用 目前,文件拥有者只关联视图控制器的 view 插座变量。一个插座变量就是一个属性(通常是一个 实例变量),只不过这个属性和 nib 文件中的某个项关联在一起。此处的关联表明当 nib 文件被加载并 且 UIView 的实例解档之后,视图控制器的 view 实例变量会被设定指向 nib 文件中的视图。 3.5.5 如何加载 Nib 文件 视图控制器在 loadView 方法中会自动加载 nib 文件。加载哪个文件呢? 请回想一下, 在 initWithNibName:bundle:方法的第一个参数已指定所要加载的 nib 文件的名称了。(请参看“创建一个视 图控制器实例”一节)。通常情况下,在视图控制器整个生存过程中,loadView 方法只调用一次,目的 是为了创建视图。当 调用视图控制器的 view 方法时,如果视图尚未被创建出来,则控制器会自动调用 自己的 loadView 方法。(如果视图控制器由于接收到内存警告而清除了自己的视图,则在必要的时候, loadView 方法会被再次调用以创建视图)。 如果希望编程创建视图控制器的视图,则可以重载 loadView 方法,并在 自己的实现中创建视图。 如果 使用 initWithNibName:bundle:方法初始化一个视图控制器,但是希望在视图加载之后执行附加配 置,则应该重载控制器的 viewDidLoad 方法。 可以使用一个 NSBundle 实例自行加载 nib 文件。 3.5.6 测试应用程序 为了确信应用程序可以正确执行, 可以把视图的背景色设置成其他颜色(非白色),并在程序运 行后验证新颜色是否显示。 (1)请在 Interface Builder 中选择视图,然后选择 Tools > Attributes Inspector ,这样屏幕就会显示 Attributes inspector,如图 3-14 所示。 (2)请点击 Background 选色板上的方框,让颜色面板显示在屏幕上。然后在其中选择一种不同的 颜色。 图 3-14 视图属性设置 (3)保存 nib 文件 (4)编译并运行工程(请点击工具栏中的 Build and Go 按键)。 应用程序应该可以正确编译,而后应该可以再次在模拟器里看到具有恰当颜色的屏幕。 (5)请把视图的背景颜色恢复成白色并保存 nib 文件。 3.6 如何配置视图 Interface Builder 包含一个对象库, 可以将其中的对象添加至 nib 文件。在这个对象库里,一部分 是用户接口元素,例如按键和文本字段; 其它则是控制器对象,例如视图控制器。 的 nib 文件已含有 一个视图-现在, 只需要添加按键和文本字段。 3.6.1 添加用户接口元素 只要将用户接口元素从 Interface Builder 库拖过来,就可以将其添加至视图,如图 3-15 所示。 (1)请在 Interface Builder 中选择 Tools > Library,让对象库的窗口显示在屏幕上 可以从对象库中拖动视图项,然后将其放在视图上面,这和 在一个绘画应用里执行的动作相似。 图 3-15 添加用户接口元素 (2)请在视图上添加一个文本字段(UITextField),一个标签 (UILabel)以及一个按键(UIButton)。 接下来, 可以使用视图项适当位置的尺寸调整点来调整尺寸,可以拖动这些视图项来进行重定位。 当在视图内移动视图项时,视图上会出现蓝色的点划线,这是对齐引导线。 (3)请根据下图 3-16 排布视图中的控件。 图 3-16 View 中包含数个用户接口元素以及一条蓝色的引导线 (4)接下来,请执行下述操作:  请在文本字段的属性查看器里输入 Your Name,这将作为文本字段的占位字符串。  调整标签的尺寸,将其扩展至与视图等宽。  删除标签中的文本(“Label”), 可以在标签的属性查看器里删除,也可以直接选中文本(双击可 执行选中操作)再按删除键进行删除。  给按键添加一个标题,请在按键中双击鼠标,然后输入 Hello。  请使用查看器将文本字段和标签的文本对齐方式都设置为居中对齐。 最后的视图应该如图 3-17 所示。 图 3-17 视图设置布局 (5)请勾选标签属性查看器视图区域中的 Clear Context Before Drawing 选项。这是为确保在更新祝 贺词的时候,标签会先删除之前的字符串再绘制新字符串。如果不这样做,字符串就会相互重叠。 还需要对文本字段执行几处更改-第一处改动显而易见,其它改动向则不然。首先,可能希望名称 首字符大写。第二, 可能希望合理地配置文本字段的关联键盘,以便用户输入名称。同时,键盘上还 需要显示一个 Done 按键。 执行这些变动的指导原则是:当文本字段被放到视图时, 知道它所应包含的内容。因此, 应该合 理地设计文本字段,使得运行时键盘可以恰当地配置自己,从而更好地适应用户的任务。 可以在文本 字段的文本输入特征中完成这些设置。 (6)请选择 Interface Builder 中的文本字段,然后选择它的属性查看器。请在属性查看器的文本输 入特征区域中执行下述选择:  在 Capitalize 弹出菜单中, 请选择 Words  在 Keyboard Type 弹出菜单中,请选择 Default  在 Keyboard Return Key 弹出菜单中,请选择 Done (7)请保存文件。 如果在 Xcode 上编译并运行应用程序,当程序运行起来时, 会看到用户接口元素根据 指定的位置 摆放。按下视图中的按键,它会变成高亮,在文本字段里点一下,键盘会显示出来。但是目前,没有办 法让键盘消失。 需要在视图控制器和其它对象之间建立恰当的关联,才能解决该问题,也才能添加其 他功能。这些内容将在下部分介绍。 3.6.2 视图控制器接口声明 为了建立视图控制器到用户接口的关联, 需要指定一些插座变量(之前说过插座变量就是实例变 量)。同时 还需要一个非常简单的模型对象的声明,一个字符串即可。 (1)请在 Xcode MyViewController.h 文件中的 MyViewController 类里面添加下面的实例变量: UITextField *textField; UILabel *label; NSString *string; (2)然后 需要为这些实例变量添加属性声明, 同时还需添加一个 changeGreeting:动作方法的声 明: @property (nonatomic, retain) IBOutlet UITextField *textField; @property (nonatomic, retain) IBOutlet UILabel *label; @property (nonatomic, copy) NSString *string; - (IBAction)changeGreeting:(id)sender; IBOutlet 是一个特殊的关键字,它唯一的作用是通知 Interface Builder 将某个实例变量或者属性当成 插座变量。实际上,这个关键字被定义为空白,因此在编译的时候它没有任何作用。 IBAction 是一个特殊的关键字,它唯一的作用是告诉 Interface Builder 将某个方法当成目标/动作关 联中的动作。它被定义为 void。 视图控制器还将作为文本字段的委托,因此它必须采用 UITextFieldDelegate 协议。如希望指定一个 类采用某种协议,请在接口继承的类的名称后面添加协议名称,并将其放在尖括号(<>) 中。 (3) 请在 UIViewController 后面添加,这是为了让 UIViewController 对象采 用 UITextFieldDelegate 协议。 的接口文件应如下所示: #import @interface MyViewController : UIViewController { UITextField *textField; UILabel *label; NSString *string; } @property (nonatomic, retain) IBOutlet UITextField *textField; @property (nonatomic, retain) IBOutlet UILabel *label; @property (nonatomic, copy) NSString *string; - (IBAction)changeGreeting:(id)sender; @end (3)保存 MyViewController.h 文件,以便让 Interface Builder 注意到上述改动。 本节末, 就可以对项目进行测试。请在实现文件(即 MyViewController.m)中实现一个空的 changeGreeting:方法。 请在@implementation MyViewController 一行后面添加: - (IBAction)changeGreeting:(id)sender { } 然后保存文件。 3.6.3 教你如何制定关联 已经定义了视图控制器的插座变量和动作,现在开始在 nib 文件中建立关联。 关联标签和文本字段的插座变更。按下 Contrl 键并点击文件拥有者,一个半透明的面板就会显示出 来,如图 3-18 所示,面板里面显示了所有可用的插座变量和动作。请将光标从列表右边的圆圈拖动到 所要关联的视图项上面,这样就可以建立二者之间的关联。 图 3-18 插座和动作的关联 可以通过面板右下角的尺寸调整角来调整面板尺寸,让它一次所能显示的插座变量和动作减少一 些。如果面板没有足够的空间来显示所有的插座变量和动作,则其上会出现滚动条, 可以使用它在列 表视图里导航。 Interface Builder 不允许 将插座变量和一个错误类型的元素关联在一起
本文档为【第3章 创建你的第一个iPhone应用程序】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_119574
暂无简介~
格式:pdf
大小:1MB
软件:PDF阅读器
页数:0
分类:互联网
上传时间:2014-03-23
浏览量:18