《精通iOS开发(第6版)》文前及前3章


内 容 提 要 本书是 iOS 应用开发基础教程,内容翔实,语言生动。作者结合大量实例,循序渐进地讲解了适用于 iPhone/iPad 开发的基本流程。新版介绍强大的 iOS 7 操作系统,涵盖 Xcode 4 以来的新功能,书中所有案例 全部重新编写。 本书具有较强通用性,iOS 开发新手可通过本书快速入门进阶,经验丰富的 iOS 开发人员也能从中找 到令人耳目一新的内容。 定价:109.00元 读者服务热线:(010)51095186转600 印装质量热线:(010)81055316 反盗版热线:(010)81055315 广告经营许可证:京崇工商广字第 0021 号 著    [瑞典] Jack Nutting [法] Fredrik Olsson      [美] David Mark [美] Jeff LaMarche 译    周庆成 邓 强 武海峰 责任编辑 朱 巍 执行编辑 李 鑫 责任印制 焦志炜 人民邮电出版社出版发行  北京市丰台区成寿寺路11号 邮编 100164  电子邮件 315@ptpress.com.cn 网址 http://www.ptpress.com.cn 北京      印刷 开本:800×1000 1/16 印张:34.25 字数:809千字 2014年 10 月第 1 版 印数:1 — 3 000册 2014年 10 月北京第 1 次印刷 著作权合同登记号 图字:01-2014-5227号 ◆ ◆ ◆ 错误!文档中没有指定样式的文字。 1 1 2 3 4 5 11 6 7 8 9 10 版 权 声 明 Original English language edition, entitled Benginning iOS 7 Development: Exploring the iOS SDK by Jack Nutting, Fredrik Olsson, David Mark, Jeff LaMarche, published by Apress, 2855 Telegraph Avenue, Suite600, Berkeley, CA94705 USA. Copyright © 2014 by Jack Nutting, Fredrik Olsson, David Mark and Jeff LaMarche.Simplified Chinese-language edition copyright © 2014 by Posts&Telecom Press.All righrs reserved. 本书中文简体字版由 Apress L.P.授权人民邮电出版社独家出版。未经出版者书面许可,不得 以任何方式复制或抄袭本书内容。 版权所有,侵权必究。 4 前 言 译 者 序 iOS 7 是 iOS 系统自 2007 年 iPhone 发布以来最大一次升级,由苹果公司在 2013 年 6 月 10 日 举办的全球开发者大会(WWDC)上对外公布,其支持 iPhone 4 及以后机型、第 5 代 iPod touch、 iPad 2 及以后机型,等等。 iOS 7 重新设计了用户界面并对操作系统的功能进行了改进,它采用全新的扁平化界面设计, 总计有上百项改动,其中包括控制中心 、通知中心、多任务处理能力等。iOS 7 还特别针对中国 用户的输入习惯改进了中文输入法,增加了九宫格输入方式。就在翻译此书时,iOS 7 的安装率 已经达到 91%,成为 iOS 设备上主流的操作系统。 iOS 7在用户界面上有着与之前版本完全不同的视觉设计,应用程序的图标变得更锐利,在许多 地方采用了较为纤细的字体,以往的拟物风格在 iOS 7 中不再出现。虽然扁平化风格界面并非苹果最 早采用,但在视觉体验上,iOS 7 依然拥有自己的特色。新的界面色彩更为鲜艳,饱和度更加突出, 通过渐变和半透明更好地阐释了苹果一贯的简单至上的设计原则。iOS 7 的画面采用类 3D 的效果, 在锁定画面及主屏幕会有立体的效果。所有的内置应用程序、解锁画面与通知中心也经过重新设计。 此外 iOS 7 也新增了控制中心界面,让用户能够快速控制各种系统功能的开关(包括飞行模 式、蓝牙、Wi-Fi 网络等)并调整屏幕亮度、播放或暂停音乐等。后台多任务处理功能也经过了 强化,现在能够支持每一种应用程序,切换程序时也采用了新的交互方式。 本书全面介绍了 iOS 7 开发的基础知识,结构清晰,内容丰富,通过 22 章由浅入深涵盖了 iOS 7 所有的关键内容。与上一版相比,本书增加了游戏开发 SDK 教程,并对许多章节进行了大量的优化改 进,其中第 9章为了配合 iOS 7 的新特性重写了全部内容,从而能够更好地展示使用新系统开发的优势。 随着 iOS 的不断升级,这本书也迎来了第 6 版。我曾阅读过从本书最初到现在的所有版本, 学习过程中难免会遇到一些翻译失当或难以理解的地方,也向图灵公司提出了一些勘误的意见。 这次新版出来时,我向出版社自荐来改善这本书一些遗留的历史问题,希望让读者可以更轻松地 理解原作者的想法,简化程序员向移动开发入门的难度。虽然在校订过程中修改了很多细节,尽 可能地保证质量,但仍可能会有遗漏,希望读者能给出合理的意见。 这本书能够顺利翻译完成,首先要感谢我的家人对我的支持,以及出版社对我的信任。还要 特别感谢图灵公司的编辑李鑫,他认真地对全稿进行了审阅。此外还要感谢好友蒋振华,他对书 中许多内容提出了自己的看法。当然,还要感谢苹果公司所提供的如此便利的开发平台以及原作 者的辛勤劳动。 ——周庆成 前 言 1 1 2 3 5 7 10 12 8 9 4 6 11 关于本书 本书内容非常丰富。如果你读的是纸质书,就能明白我的意思,如果买的是电子书,就不容 易发现这点。我只想说,它比我见过的各种经典书籍还要厚。当然,这并非是说,我是经典书籍 或某方面的行家,但你们只需要明白它很大很重就对了。如果你想知道这本书是否比面包箱还大, 我可以明确地告诉你,差不多真的有那么大。然而,本书结构划分得条理明确,各部分内容也十 分简洁扼要,你完全可以在某个愉快的下午尽情揣摩某一章节的内容。这种“揣摩”并不仅仅指 的是通过阅读来了解每章内容,还需要在你的 Mac 电脑上,用自己的方式来学习与实践本书的 知识。如果在阅读每一章时,能够构建其中所有的示例应用,则有助于加深对使用模式和相关概 念的理解,而光靠阅读显然是无法做到这一点的。如果完整通读此书,就会对 iOS 应用程序开发 的基本概念有很好的理解,也就可以更好地构建自己的 iOS 应用了。 许多年前,我曾与 Torfrid Olsson(已故)见过一面,他是一位瑞典北方农村的雕刻家。对于 他生活的某一方面,我表示羡慕和钦佩,但他的回答也令我不禁深思:“嗯,这些只是书上讲的。 每个人的生活都是独特的,你怎么会认为你的生活是残缺的呢?”我希望你要善于利用书中的知 识,不要满足于读懂。阅读当然是必要的,但也要实践和理解其中的内容,甚至要敢于质疑或推 翻其中的内容,真正掌握这些知识。 ——Jack Nutting 斯德哥尔摩,2014 年 6 致 谢 致 谢 感谢 Apress 所有员工,正是由于他们的努力工作,才能完成这本如此厚实的书。他们的付 出与帮助是至关重要的。尤其需要感谢 Anamika Panchoo,直到出版的最后阶段,她都在鉴定全 书插图的正确性——要知道,当时她已经不用负责这方面工作了,大部分工作的负责人是 Melissa Maldonado。没有这些编辑勤奋耐心的校正,本书是不可能完成的。Patrick Meader 修改了大量的 文法错误,而 Nick Waynik 则把杂乱的代码排版得井井有条。Tom Welsh、Douglas Pundick 和 Matt Moodie 三人轮流担当执行编辑,确保了每章内容条理分明,易于理解。当然,对于负责编排索 引、页面排版、印刷零售(以及很多我不知道的工作)的工作人员来说,尽管你们经常被人忽视, 我们也要衷心对你们表达莫大的感激之情。尽管身为作者,我们没能和你们直接接触过,甚至也 不知道你们的名字,但我明白你们做的事都非常有意义,再接再厉! 目 录 1 目 录 第 1 章 欢迎来到 iOS 世界 ............................1 1.1 关于本书....................................................1 1.2 必要条件....................................................1 1.2.1 开发者选项 ....................................3 1.2.2 必备知识........................................3 1.3 编写iOS 应用程序有何不同 .....................4 1.3.1 只能同时运行一个应用 .................4 1.3.2 只有一个窗口.................................4 1.3.3 有限的访问权限.............................5 1.3.4 有限的响应时间.............................5 1.3.5 有限的屏幕大小.............................5 1.3.6 有限的系统资源.............................5 1.3.7 不支持垃圾回收.............................6 1.3.8 新功能............................................6 1.3.9 与众不同的交互方法 .....................6 1.4 本书内容....................................................7 1.5 这一版的新内容 ........................................8 1.6 准备开始吧................................................9 第 2 章 创建项目............................................10 2.1 在Xcode 中创建项目 ..............................10 2.1.1 Xcode 项目窗口 ...........................14 2.1.2 深入研究项目...............................22 2.2 界面构建器简介 ......................................23 2.2.1 文件格式......................................24 2.2.2 分镜..............................................25 2.2.3 库..................................................26 2.2.4 在视图中添加标签.......................27 2.2.5 属性修改......................................29 2.3 画龙点睛——美化 iPhone 应用 ..............31 2.4 小结.........................................................33 第 3 章 实现基本交互 ...................................34 3.1 MVC 方法................................................34 3.2 创建项目..................................................35 3.3 视图控制器..............................................36 3.3.1 输出接口和操作方法...................37 3.3.2 清理视图控制器...........................40 3.3.3 设计用户界面 ..............................40 3.3.4 运行应用......................................50 3.3.5 样式文本......................................50 3.4 应用程序委托..........................................51 3.5 小结.........................................................54 第 4 章 更丰富的用户界面...........................55 4.1 满是控件的屏幕 ......................................55 4.2 活跃控件、静态控件和被动控件 ...........57 4.3 创建应用程序..........................................58 4.4 实现图像视图和文本框...........................59 4.4.1 添加图像视图 ..............................59 4.4.2 调整图像视图的大小...................62 4.4.3 设置视图属性 ..............................63 4.4.4 添加文本框 ..................................65 4.4.5 创建并关联输出接口...................71 4.5 关闭键盘..................................................73 4.5.1 输入完成后关闭键盘...................73 4.5.2 通过触摸背景关闭键盘 ...............74 4.5.3 添加滑动条和标签.......................77 4.5.4 添加顶部约束 ..............................78 4.5.5 创建并关联操作方法和输出 接口..............................................79 4.5.6 实现操作方法 ..............................79 4.6 实现开关、按钮和分段控件...................80 2 目 录 4.6.1 添加两个带标签的开关...............81 4.6.2 为开关创建并关联输出接口和 操作方法......................................83 4.6.3 实现开关的操作方法...................83 4.7 美化按钮 .................................................85 4.7.1 可拉伸图像 ..................................85 4.7.2 控件状态......................................86 4.7.3 为按钮创建并关联输出接口和 操作方法......................................87 4.8 实现分段控件的操作方法.......................87 4.9 实现操作表单和警告视图.......................88 4.9.1 遵从操作表单委托方法...............88 4.9.2 显示操作表单 ..............................89 4.9.3 最终调整......................................92 4.10 小结.......................................................92 第 5 章 自动旋转和自动调整大小..............93 5.1 自动旋转机制..........................................93 5.1.1 点、像素和 Retina 显示屏...........94 5.1.2 自动旋转的实现方式...................95 5.2 选择视图支持的方向 ..............................95 5.2.1 应用级支持的方向.......................96 5.2.2 单个控制器的旋转支持...............97 5.3 使用约束设计界面 ..................................99 5.3.1 覆盖默认的约束 ........................101 5.3.2 与屏幕等宽的标签.....................102 5.4 旋转时重构视图....................................104 5.4.1 创建并关联输出接口.................106 5.4.2 旋转时移动按钮 ........................106 5.5 小结.......................................................109 第 6 章 多视图应用 .....................................110 6.1 多视图应用的常见类型.........................110 6.2 多视图应用的体系结构.........................113 6.2.1 根控制器....................................115 6.2.2 内容视图剖析 ............................116 6.3 构建View Switcher 项目 ......................116 6.3.1 创建视图控制器和分镜.............117 6.3.2 修改应用委托 ............................119 6.3.3 修改BIDSwitchView Controller.m............................... 120 6.3.4 添加视图控制器 ........................ 120 6.3.5 构建带有工具栏的视图............. 122 6.3.6 编写根视图控制器 .................... 124 6.3.7 实现内容视图 ............................ 127 6.3.8 转换过程的动画效果................. 130 6.4 小结....................................................... 132 第 7 章 分页栏与选取器............................. 133 7.1 Pickers 应用程序................................... 134 7.2 委托和数据源........................................ 136 7.3 创建Pickers 应用程序 .......................... 136 7.3.1 创建视图控制器 ........................ 136 7.3.2 添加分镜.................................... 137 7.3.3 创建分页栏控制器 .................... 138 7.3.4 初次运行.................................... 140 7.4 实现日期选取器.................................... 141 7.5 实现单滚轮选取器................................ 144 7.5.1 构建视图.................................... 144 7.5.2 将控制器实现为数据源和 委托 ........................................... 145 7.6 实现多滚轮取器.................................... 149 7.6.1 声明输出接口和操作方法......... 149 7.6.2 构建视图.................................... 149 7.6.3 实现控制器................................ 150 7.7 实现内容取决于滚轮 ............................ 152 7.8 使用自定义选取器创建一个简单 游戏....................................................... 158 7.8.1 编写控制器头文件 .................... 158 7.8.2 构建视图.................................... 159 7.8.3 添加图像资源 ............................ 160 7.8.4 实现控制器................................ 160 7.8.5 最后的细节................................ 163 7.9 小结....................................................... 166 第 8 章 表视图简介 ..................................... 167 8.1 表视图基础 ........................................... 167 8.1.1 表视图和表视图单元................. 168 8.1.2 分组表和无格式表 .................... 168 目 录 3 8.2 实现一个简单表 ....................................170 8.2.1 设计视图....................................170 8.2.2 编写控制器 ................................171 8.2.3 添加一个图像.............................175 8.2.4 表视图单元样式.........................176 8.2.5 设置缩进级别.............................178 8.2.6 处理行的选择.............................179 8.2.7 更改字体大小和行高 .................180 8.3 定制表视图单元 ....................................182 8.3.1 向表视图单元添加子视图..........182 8.3.2 创建UITableViewCell 子类........183 8.3.3 从nib 文件加载 UITableViewCell .........................187 8.4 分组分区和索引分区.............................191 8.4.1 构建视图....................................191 8.4.2 导入数据....................................191 8.4.3 实现控制器 ................................192 8.4.4 添加索引....................................196 8.5 解决状态栏干扰 ....................................197 8.6 实现搜索栏............................................198 8.7 小结.......................................................203 第 9 章 导航控制器和表视图.....................204 9.1 导航控制器............................................204 9.1.1 栈的概念....................................204 9.1.2 控制器栈....................................205 9.2 一个简单的字体浏览器:Fonts ............206 9.2.1 子控制器....................................207 9.2.2 Font 应用的基础框架.................209 9.3 创建根视图控制器 ................................213 9.4 初始化分镜............................................216 9.5 第一个子控制器:字体列表视图..........218 9.5.1 设定字体列表的分镜 .................220 9.5.2 对根视图控制器的转场进行 设置............................................221 9.6 创建字体尺寸视图控制器.....................222 9.6.1 设计字体尺寸视图控制器的 分镜............................................224 9.6.2 对字体列表视图控制器的转 场进行设置 ................................224 9.7 创建字体信息视图控制器.....................225 9.7.1 设计字体信息视图控制器的 分镜............................................226 9.7.2 设置约束....................................227 9.7.3 调整字体列表视图控制器的 转场............................................228 9.7.4 我的收藏字体 ............................229 9.8 改善表视图............................................229 9.8.1 实现轻扫删除 ............................230 9.8.2 实现拖动排序 ............................231 9.9 小结.......................................................232 第 10 章 集合视图 .......................................233 10.1 创建DialogViewer 项目......................233 10.2 修补视图控制器类 ..............................234 10.3 自定义单元..........................................235 10.4 配置视图控制器 ..................................237 10.5 内容单元..............................................239 10.6 实现流式布局......................................240 10.7 分区标题视图......................................241 10.8 小结.....................................................243 第 11 章 iPad 开发注意事项......................244 11.1 分割视图和浮动窗口...........................244 11.1.1 创建SplitView 项目...............246 11.1.2 在分镜中定义结构.................248 11.1.3 使用代码定义功能.................250 11.2 显示总统信息......................................256 11.3 创建浮动窗口......................................261 11.4 小结.....................................................267 第 12 章 应用设置及用户默认设置..........268 12.1 设置捆绑包入门 ..................................268 12.2 应用:Bridge Control..........................269 12.2.1 创建项目 ................................272 12.2.2 使用设置捆绑包.....................273 12.2.3 读取应用中的设置.................286 12.2.4 在应用中修改默认设置 .........289 12.2.5 注册默认值 ............................292 12.2.6 保证设置有效.........................293 12.3 小结.....................................................295 4 目 录 第 13 章 数据持久化基础知识 ..................296 13.1 应用的沙盒..........................................296 13.1.1 获取Documents 目录.............297 13.1.2 获取tmp 目录 ........................298 13.2 文件保存方案......................................298 13.2.1 单文件持久化 ........................299 13.2.2 多文件持久化 ........................299 13.3 属性列表..............................................299 13.3.1 属性列表序列化.....................299 13.3.2 Persistence 应用的第一个 版本........................................300 13.4 对模型对象进行归档 ..........................305 13.4.1 遵循NSCoding 协议 ................305 13.4.2 实现NSCopying 协议 ..............306 13.4.3 对数据对象进行归档和取消 归档........................................307 13.4.4 归档应用 ................................308 13.5 使用iOS 内嵌的 SQLite3....................311 13.5.1 创建或打开数据库.................312 13.5.2 绑定变量 ................................313 13.5.3 SQLite3 应用..........................314 13.6 使用Core Data ....................................320 13.6.1 实体和托管对象.....................321 13.6.2 Core Data 应用.......................324 13.7 小结.....................................................333 第 14 章 iCloud 之旅...................................334 14.1 使用UIDocument 管理文档存储.........334 14.1.1 构建TinyPix ..........................335 14.1.2 创建BIDTinyPixDocument 类.....336 14.1.3 主控制器代码 ........................338 14.1.4 初始分镜 ................................345 14.1.5 创建BIDTinyPixView 类 .........347 14.1.6 设计分镜 ................................351 14.2 添加iCloud 支持 .................................353 14.2.1 创建授权文件 ........................353 14.2.2 如何查询 ................................354 14.2.3 保存在哪里 ............................356 14.2.4 将首选项保存到 iCloud.........357 14.3 小结.....................................................358 第 15 章 Grand Central Dispatch 和 后台处理....................................... 359 15.1 Grand Central Dispatch ....................... 359 15.2 SlowWorker 简介 ................................ 360 15.3 线程基础知识...................................... 362 15.4 工作单元............................................. 363 15.5 GCD:底层队列 ................................. 364 15.5.1 傻瓜式操作............................ 364 15.5.2 改进SlowWorker................... 365 15.6 后台处理............................................. 370 15.6.1 应用生命周期 ........................ 371 15.6.2 状态更改通知 ........................ 372 15.6.3 创建State Lab 项目 ............... 373 15.6.4 执行状态的变化 .................... 374 15.6.5 利用执行状态更改................. 376 15.6.6 处理不活跃状态 .................... 377 15.6.7 处理后台状态 ........................ 380 15.7 小结..................................................... 387 第 16 章 使用 Core Graphics 绘图 ......... 388 16.1 Quartz 2D 基础概念 ............................ 388 16.2 Quartz 2D 绘图方法 ............................ 388 16.2.1 Quartz 2D 图形环境............... 389 16.2.2 坐标系统................................ 390 16.2.3 指定颜色................................ 391 16.2.4 在环境中绘制图像................. 393 16.2.5 绘制形状:多边形、直线 和曲线.................................... 393 16.2.6 Quartz 2D 样例:图案、渐 变色、虚线图 ........................ 394 16.3 QuartzFun 应用程序............................ 394 16.3.1 构建QuartzFun 应用程序...... 395 16.3.2 添加Quartz 2D 绘制代码 ...... 404 16.3.3 优化QuartzFun 应用程序...... 409 16.4 小结..................................................... 412 第 17 章 Sprite Kit 游戏框架..................... 413 17.1 基础入门............................................. 413 17.1.1 自定义初始场景 .................... 414 17.1.2 隐藏状态栏............................ 415 目 录 5 17.2 场景设置..............................................415 17.3 玩家动作..............................................418 17.3.1 向场景中插入玩家 .................418 17.3.2 触摸处理 ................................419 17.3.3 玩家移动 ................................420 17.3.4 几何运算 ................................421 17.3.5 轻微摆动 ................................421 17.4 创建你的敌人 ......................................422 17.5 在场景中放入敌人...............................423 17.6 开始射击..............................................425 17.6.1 定义物理类别.........................425 17.6.2 创建BIDBulletNode 类............425 17.6.3 应用物理知识.........................427 17.6.4 在场景中添加导弹 .................427 17.7 利用物理引擎攻击敌人.......................429 17.8 实现关卡..............................................431 17.8.1 注意敌人 ................................431 17.8.2 进入下一关卡.........................431 17.9 自定义碰撞..........................................433 17.9.1 为SKNode 添加类别...............434 17.9.2 向敌人添加自定义碰撞行 为............................................435 17.9.3 准确显示玩家生命 .................436 17.10 粒子系统............................................437 17.10.1 第一个粒子.........................437 17.10.2 向场景中加入粒子 .............440 17.11 游戏结束............................................441 17.12 开始场景............................................443 17.13 播放音乐............................................445 17.14 小结....................................................446 第 18 章 轻点、触摸和手势.......................447 18.1 多点触控术语 ......................................447 18.2 响应者链..............................................448 18.2.1 响应事件 ................................448 18.2.2 转发事件:保持响应者链 的活动状态.............................449 18.3 多点触控体系结构...............................450 18.4 4 个手势通知方法................................450 18.5 TouchExplorer 应用 .............................451 18.6 Swipes 应用 .........................................454 18.6.1 自动手势识别.........................457 18.6.2 实现多指轻扫.........................459 18.7 检测多次轻点......................................460 18.8 检测捏合和旋转 ..................................465 18.9 自定义手势..........................................469 18.9.1 CheckPlease 应用 ...................470 18.9.2 CheckPlease 的触摸方法........472 18.10 小结...................................................474 第 19 章 Core Location 和 Map Kit.........475 19.1 位置管理器..........................................476 19.1.1 设置精度 ................................476 19.1.2 设置距离筛选器.....................476 19.1.3 启动位置管理器.....................477 19.1.4 合理使用位置管理器.............477 19.2 位置管理器委托 ..................................477 19.2.1 获取位置更新.........................477 19.2.2 使用CLLocation 获取纬度 和经度....................................477 19.2.3 错误通知 ................................479 19.3 开始构建Core Location ......................480 19.4 将移动路线展现在地图上...................484 19.5 小结.....................................................488 第 20 章 陀螺仪和加速计...........................489 20.1 加速计物理特性 ..................................489 20.2 陀螺仪旋转特性 ..................................490 20.3 Core Motion 和动作管理器 .................490 20.3.1 基于事件的动作.....................491 20.3.2 主动动作访问.........................496 20.3.3 加速计结果 ............................498 20.4 检测摇动..............................................498 20.4.1 内嵌的摇动检测.....................499 20.4.2 摇动与击碎 ............................500 20.5 将加速计用做方向控制器...................502 20.5.1 滚弹珠程序 ............................503 20.5.2 实现BIDBallView 类...............505 20.5.3 计算弹珠运动.........................508 20.6 小结.....................................................510 6 目 录 第 21 章 摄像头和照片库...........................511 21.1 图像选取器和 UIImagePicker- Controller ............................................511 21.2 实现图像选取器控制器委托...............513 21.3 实际测试摄像头和照片库...................514 21.3.1 设计界面 ................................515 21.3.2 实现摄像头视图控制器 .........515 21.4 小结.....................................................519 第 22 章 应用本地化...................................520 22.1 本地化体系结构 ..................................520 22.2 字符串文件.......................................... 521 22.2.1 字符串文件............................ 522 22.2.2 本地化的字符串宏................. 522 22.3 现实中的iOS 本地化应用 .................. 523 22.3.1 创建LocalizeMe.................... 523 22.3.2 测试LocalizeMe.................... 526 22.3.3 本地化项目............................ 527 22.3.4 初始化分镜............................ 530 22.3.5 创建并本地化字符串文件 ..... 532 22.3.6 应用显示名称的本地化......... 535 22.4 小结..................................................... 536 1.2 必要条件 1 1 2 3 4 5 11 6 7 8 9 10 欢迎来到 iOS 世界 这么说,你想编写 iPhone、iPod touch 和 iPad 应用程序?哦,当然可以。作为所有苹果设备 的核心软件,iOS 从 2007 年发布以来发展异常迅速,是个极具吸引力的平台。移动应用平台的 崛起意味着人们无时无刻不在使用各种软件。随着 iOS 7、Xcode 5 以及最新 iOS 软件开发工具包 (SDK)的发布,开发 iOS 应用正变得更加高效、更加有趣。 1.1 关于本书 本书是 iOS 应用编程的入门指南,旨在帮助你克服入门的困难,帮助你理解 iOS 应用程序的 运行和构建方式。 在学习的过程中,你将会创建一系列小型应用程序,每个应用程序都会突出某些 iOS 特性, 展示如何控制这些特性,以及如何与其交互。如果你扎实地掌握了本书的基础知识,充分发挥自 己的创造力,并且持之以恒,再借助大量条理清晰的苹果文档,你就可以创建出专业的 iPhone 和 iPad 应用。 提示 Dave、Jack、Jeff 和 Fredrik 为本书创办了一个论坛。志趣相投者可会聚于此,相互答疑 解惑。一定要访问这个论坛哦!地址是 http://forum.learncocoa.org。 1.2 必要条件 开始编写 iOS 应用程序之前,需要做一些准备工作。初学者需要一台安装了 Mountain Lion (OS X 10.8)或 Mavericks(OS X 10.9)甚至更高版本的基于 Intel 架构的 Macintosh 计算机。任 何最近上市的基于 Intel 架构的 Macintosh 计算机(台式机或笔记本)均可。 如果想访问到苹果更强大的全新开发工具,你需要注册成为 iOS 开发者。只需要访问 http://developr.apple.com/ios/链接就可以创建你的开发者账号了。你会看到如图 1-1 所示的页面。 首先,点击 Log in 按钮,页面将提示你输入 Apple ID。如果没有 Apple ID,就点击 Join now 创建一个 ID,然后再登录。登录之后就进入了 iOS 开发中心的主页面。其中有各类文档、视频 和示例代码等的链接,所有这些都可帮助你更好地进行 iOS 应用开发。 第1章 2 第1 章 欢迎来到 iOS 世界 图 1-1 苹果的 iOS 开发中心网站 iOS 开发中最重要的工具是 Xcode,它是苹果的集成开发环境(IDE)。Xcode 提供了一些实 用工具,用于创建和调试源代码、编译应用程序,以及对应用程序进行性能调优。 可以从 Mac App Store 下载 Xcode(可以通过 Mac 的 Apple 菜单访问 App Store)。 书中示例使用的 SDK 版本和源代码 随着 SDK 和 Xcode 版本的不断更新,它们的下载方式也在发生变化。在最近几年内,苹 果已经开始把当前“稳定”版本的 Xcode 和 iOS SDK 放在 Mac App Store 中了,同时也会在开 发者网站上提供预览版供开发者下载。总之,如果想下载 Xcode 和 iOS SDK 的最新版本(非 beta 版),应该使用 Mac App Store。 本书面向最新版 SDK。在一些地方,我们会使用 iOS 7 中引入的新函数或方法,它们可能 与旧版 SDK 不兼容。当然,出现这些情况时我们会特别指出。 请从 http://learncocoa.org 或者本书论坛 http://forum.learncocoa.org 上下载最新的源代码①。 当有新版 SDK 发布时,我们会及时更新代码,所以你应该定期登录这些网站,看看是否有更 新内容。 —————————— ① 本书源代码也可从图灵社区本书页面“随书下载”部分下载,网址是 http://www.ituring.com.cn/book/1390。 ——编者注 1.2 必要条件 3 1 2 3 4 5 11 6 7 8 9 10 1.2.1 开发者选项 免费下载的 Xcode 中包含一个模拟器,使用这个模拟器,就可以在 Mac 上创建并运行 iPhone 和 iPad 应用。这个模拟器对于学习编写 iOS 程序极其有用。但是,模拟器不支持那些依赖于硬 件的特性,比如加速计和摄像头。另外,免费下载的 SDK 不支持把应用程序安装到 iPhone 等 iOS 真机设备中,也不能在苹果的 App Store 上出售应用。如果想要这些功能,需要注册一个付费选项。  标准版计划的价格为 99 美元/年。它提供了大量的开发工具和资源,以及技术支持,还可 以通过苹果的 App Store 出售应用。最重要的是,它允许在 iOS 设备上(而不只是在模拟 器上)测试和调试代码。  企业版计划的价格为 299 美元/年。如果需要开发公司内部使用的私有 iOS 应用程序,可 以选择这个计划。 可以访问 http://developer.apple.com/programs/ios(标准版计划)和 http://developer.apple.com/ programs/ios/enterprise(企业版计划)来查看这两个计划的详细信息。 对于 iOS 所支持的始终联网的移动设备(比如 iPhone),由于这种设备使用的是其他公司的 无线基础设施,因此苹果对 iOS 开发人员的限制比对 Mac 开发人员严格得多(目前,Mac 开发 人员无需经过苹果的审查或批准就可以编写并销售程序)。虽然 iPod touch 和那种只支持 Wi-Fi 的 iPad 不使用其他公司的基础设施,但是它们也受到同样的限制。 苹果添加这些限制,主要是为了尽量避免发布恶意程序和不良程序,因为这类程序可能会在 共享网络中降低性能。开发 iOS 应用似乎有很高的门槛,但是苹果也为简化开发过程做出了巨大 努力。值得一提的是,99 美元比 Visual Studio(微软公司的软件开发 IDE)的价格低得多。 显然,你还需要一部 iPhone、iPod touch 或 iPad。虽然很多代码都可以通过 iOS 模拟器进行 测试,但并非所有程序都是如此。即便是那些可以在模拟器上运行的应用程序,也需要在真实设 备上进行全面测试后才能对外发布。 注意 如果你准备注册标准版计划或企业版计划,最好马上注册。因为审批过程可能需要一些 时间,通过审批之后才能在真实设备上运行应用程序。不过不必担心,前几章中的所有 项目以及本书的大多数应用程序都可以在 iOS 模拟器上运行。 1.2.2 必备知识 学习本书应该具备一定的编程知识。我们假设你已经理解基本编程尤其是面向对象编程的基 础知识(例如,知道类、对象、循环、变量这些基本概念)。你还应该熟悉 Objective-C 编程语言。 本书大部分章节都需要用到 Cocoa Touch(它是 SDK 的一部分),Cocoa Touch 使用的是最新版的 Objective-C,这个版本有一些新特性。不过不了解 Objective-C 的新特性也没有关系。本书在用 到 Objective-C 的新特性时会特别指出,并解释它们的工作原理和使用原因。 作为用户,你还应该熟悉 iOS 系统本身。就像在其他平台中编写应用程序一样,你需要熟悉 4 第1 章 欢迎来到 iOS 世界 iPhone、iPad 或 iPod touch 的一些细微差别和怪异模式。花点时间去熟悉 iOS 界面以及 iPhone/iPad 应用的风格吧。 Objective-C 的学习资源 如果你从未使用 Objective-C 编写程序,下面这些资源可以作为入门读物。  《Objective-C 基础教程(第 2 版)》一书浅显易懂,是非常优秀的 Objective-C 入门读物, 作者是 Mac 编程专家 Scott Knaster、Waqar Malik 和 Mark Dalrymple。  Programming with Objective-C,这本是苹果出的 Objective-C 语言入门书。你可以在 https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWith ObjectiveC 网站上找到更多的内容。 1.3 编写iOS 应用程序有何不同 如果从未使用 Cocoa(或者它的前辈 NeXTSTEP 和 OpenStep)写过程序,你可能会发现 Cocoa Touch(用于编写 iOS 应用程序的应用程序框架)比较新奇。它与其他常用应用程序框架(如用 于构建.NET 或 Java 应用程序的框架)之间存在一些根本差异。起初你可能会有点不得要领,不 过不必担心,只要多加练习,很快就能够对 Cocoa Touch 运用自如了。 如果曾经使用 Cocoa 或 NeXTSTEP 写过程序,你会发现 iOS SDK 中有许多熟悉的身影。有 很多类都是从 Mac OS X 版本的 Cocoa 中原样移植过来的。即便是那些不同的类,也遵循相同的 基本原则和相似的设计模式。但是,Cocoa 和 Cocoa Touch 之间还是有一些不同的。 无论你的知识背景如何,都需要时刻牢记 iOS 开发与桌面应用程序开发之间的重要差异。接 下来几小节讨论这些差异。 1.3.1 只能同时运行一个应用 在 iOS 中,任意时刻只能有一个应用处于活动状态并显示在屏幕上。从 iOS 4 开始,用户 按下 Home 键后,应用程序可以在后台继续运行,但这也只限于少数情况,而且必须专门为此 编写代码。 当应用程序不处于活动状态也不是在后台运行时,它不会占用任何 CPU 资源,因此也会断 开网络连接。iOS 允许在后台进行处理,但要做到这一点,开发者需要多做些努力。 1.3.2 只有一个窗口 在台式机及笔记本的操作系统中,多个程序可以同时运行,每个程序可以创建并控制多个窗 口。而 iOS 只允许应用程序操作一个窗口。应用程序与用户的所有交互都在这个窗口中完成,而 且这个窗口的大小就是 iOS 设备屏幕的大小,是固定的。 1.3 编写iOS 应用程序有何不同 5 1 2 3 4 5 11 6 7 8 9 10 1.3.3 有限的访问权限 计算机上的程序可以访问属主用户(启动这个程序的用户)能够访问的任何内容。然而,iOS 严格限制了应用程序的访问权限。 iOS 的文件系统会为每个应用分配一块独立的区域,这块区域称为沙盒,每个应用只能对自 己沙盒内的文件进行读写。沙盒就是应用用于存储文档、首选项等任何必要数据的地方。 应用程序还会受到其他方面的限制。比如,不能访问 iOS 中端口号较小的网络端口,也不能 做那些在台式机中需要有根用户权限或管理员权限才能进行的操作。 1.3.4 有限的响应时间 由于使用方式特殊,iOS 需要能够快速响应各种事件,你的应用程序也应如此。启动应用程 序时,需要先打开它,载入首选项和数据,并尽快把主视图显示到屏幕上,这些过程要在几秒钟 内全部完成。 在应用程序运行中的任何时刻,都可以通过双击 Home 键查看最近使用的应用列表。如果用户 按 Home 键,iOS 就会返回主屏幕,应用必须快速保存一切内容并退出。如果没有在 5 秒之内保存 必要的数据并放弃对系统资源的控制,无论是否已经保存完成,应用程序进程都会被终止。有一个 API 可以在应用程序终止前申请多一些的时间来完成必要的工作。 你必须知道如何使用它才行。 1.3.5 有限的屏幕大小 iPhone 的屏幕显示效果非常出色,在相当长的一段时间里,iPhone 一直都是市场上分辨率最 高的掌上电子设备。 但是,iPhone 的显示空间并不大,与现代计算机相比,在 iPhone 上能使用的屏幕空间要小 很多。最初几代的 iPhone 屏幕分辨率只有 320 像素×480 像素,后来,从 iPhone 4 的视网膜屏幕 开始,分辨率增加到了 640 像素×960 像素。iPhone 5 的分辨率进一步提高到了 640 像素×1136 像 素。像素数量有了极大的提高,但是屏幕的显示空间却没有大的变化,因此还是不能在屏幕上摆 放更多的控件之类。小屏幕极大地影响了 iPhone 所能提供的应用种类和交互性。 iPad 的分辨率是 1024 像素×768 像素,显示空间也增加了,但也不是非常大。下面来做一个 有趣的对比,写作本书时,苹果最便宜的 iMac 的分辨率是 1920 像素×1080 像素,最便宜的笔记 本电脑(11 寸的 MacBook Air)的分辨率是 1366 像素×768 像素,而苹果最大的显示器是 27 英寸 的 LED Cinema Display 则支持高达 2560 像素×1440 像素的超高分辨率。请注意,对于 iPad 而言, 如果不出意外的话,往后的 iPad 机型(iPad2 以后的全尺寸 iPad 以及 iPad Mini Retina)都将配备 视网膜屏幕,横竖两个方向的分辨率都加倍了。但是,跟视网膜屏幕的 iPhone 一样,这块 2048 像素×1536 像素的屏幕的实际尺寸跟旧屏幕一样,仍无法像在传统的屏幕上那样使用这些像素。 1.3.6 有限的系统资源 一部拥有 512 MB 内存和 16 GB 存储空间的机器竟然需要对资源使用做很多限制,很多资深 6 第1 章 欢迎来到 iOS 世界 程序员该要笑话苹果的这种做法了。可事实确实如此。或许开发 iOS 应用程序并不像是在内存为 48 KB 的机器上编写复杂的电子表格应用,但是,由于 iOS 具备的图形特性和多种功能,内存很 容易就会耗光。 目前上市的 iOS 设备的物理内存要么是 512 MB(iPhone 4S、iPad 2、一 代 iPad mini、iPod touch 5),要么是 1024 MB(iPhone 5c、iPhone 5S、iPad Air、 iPad mini Retina),而且以后还会不断加 大。很大一部分内存被用于屏幕缓冲区和其他一些系统进程。通常,只有不到一半的内存留给应 用程序使用(实际可用内存可能会更少,尤其是现在其他的应用可以在后台运行了)。 虽然这些内存对于这种小型移动设备来说可能已经足够了,但谈到 iOS 的内存时,却还要考 虑另一个因素。现代的计算机操作系统(比如 OS X)会将未使用的内存块写到磁盘的交换文件 中。这样,当应用程序请求的内存超过计算机的实际可用内存时,它仍然可以正常运行。但是, iOS 并不会将易失性内存(比如应用程序数据)写到交换文件中。因此,应用程序的可用内存大 小受限于 iOS 设备中未使用的物理内存空间。 Cocoa Touch 提供了一种内置机制,可以在内存不足时通知应用程序。出现这种情况时,应 用程序必须释放不必要的内存空间,否则就可能被强制退出。 1.3.7 不支持垃圾回收 之前提过,Cocoa Touch 使用的是 Objective-C,但是 iOS 却并不支持一个 Objective-C 早在本 世纪初就已经有的关键特性:垃圾回收。是的,Cocoa Touch 不支持垃圾回收。为 iOS 编写程序 时需要手动管理内存,许多刚刚接触这个平台(尤其是那些从支持垃圾回收的语言转过来)的开 发者,还真有点不太适应。 但是,最新版本 iOS 支持的 Objective-C 基本解决了这个问题。这要归功于 ARC(Automatic Reference Counting,自动引用计数)功能,它解决了手动管理 Objective-C 对象占用内存的问题。 ARC 并不仅仅是垃圾回收的替代品,实际上,它在很多方面比垃圾回收更优秀。因此,从 OS X 10.8 开始,ARC 就成为了针对 Mac 应用程序的默认内存管理机制,垃圾回收则被废弃了。当然 ARC 也是 iOS 应用程序的默认内存管理机制。第 3 章会详细介绍 ARC。 1.3.8 新功能 前面提过,Cocoa Touch 缺少 Cocoa 的一些特性,但 iOS SDK 中也有一些功能是 Cocoa 目前 没有的,至少不是在每一部 Mac 上都可用。  iOS SDK 中的 Core Location 框架可以帮助应用程序确定 iOS 设备的当前地理坐标。  大部分 iOS 设备都有内置的摄像头和照片库,SDK 允许应用程序访问它们。  iOS 设备还有一个内置的运动传感器,用于检测设备的握持和移动方式。 1.3.9 与众不同的交互方法 iOS 设备没有物理键盘和鼠标,这意味着 iOS 应用与用户的交互方式跟通用计算机软件完全 1.4 本书内容 7 1 2 3 4 5 11 6 7 8 9 10 不同。幸好,大部分的交互都会由 iOS 系统完成。例如,如果应用中用到了文本框,iOS 系统就 会在用户单击这个文本框时调出软键盘,不需要开发者为此额外编写代码。 注意 所有的设备都支持通过蓝牙连接外置键盘,这提供了一种不错的键盘体验,并节省了屏 幕空间,但使用这种键盘的人仍然非常少。而且,现在依然无法连接鼠标。 1.4 本书内容 下面是本书其余各章的简要概述。  第 2 章:讲述如何使用 Xcode 的搭档 Interface Builder 创建简单的界面,并在屏幕上显示 一些文本。  第 3 章:展示与用户的交互,构建一个简单的应用程序,用于在运行时根据用户按下的 按钮动态更新显示的文本。  第 4 章:以第 3 章为基础,介绍更多的标准 iOS 用户界面控件。此外,还将介绍如何使用 警告框和操作表单提醒用户作出决策,或者通知用户发生了一些异常事件。  第 5 章:解释如何处理自动旋转和自动改变大小属性,以及使 iOS 应用程序同时支持纵 向和横向运行的机制。  第 6 章:分析更多高级用户界面,并讲述如何创建多视图应用程序。还会介绍如何在运 行时改变展示给用户的视图,这样可以创造出更强大的应用。  第 7 章:讨论如何实现标签栏和选取器等界面元素,它们是标准 iOS 用户界面的一部分。  第 8 章:介绍表视图。表视图是向用户提供数据列表的主要方法,并且是基于分层导航 的应用程序的基础。这一章还会介绍如何让用户搜索应用程序数据。  第 9 章:说明如何实现分层列表这一标准的界面类型。分层列表是最常用的 iOS 应用程 序界面之一,可以通过它查看更多详细的数据。  第 10 章:展示集合视图的使用。各种 iOS 应用程序从一开始都在使用表视图展示动态的、 垂直滚动的组件列表。在最近一段时间,苹果引入了 UICollectionView 类,用于实现集 合视图。集合视图在展示动态、垂直滚动的组件列表方面功能更加强大。使用集合视图, 开发者可以更灵活地处理视觉组件的排列。  第 11 章:讲述如何使用 SDK 中面向 iPad 的部分。iPad 的外形与其他 iOS 设备不同,它 需要用不同的方法来显示 GUI(图形用户界面),SDK 中有一些专用于 iPad 的组件。  第 12 章:展示如何实现应用程序设置,iOS 中的这种机制允许用户设置应用程序级的首选 项。  第 13 章:介绍 iOS 中的数据管理。将讨论如何创建对象来保存应用程序数据,以及如何 将这些数据持久化到 iOS 文件系统中。这一章还会介绍使用 Core Data 的基础知识,使用 Core Data 可以很方便地保存和检索数据。 8 第1 章 欢迎来到 iOS 世界  第 14 章:解释如何使用 iCloud。iCloud 是 iOS 5 引入的一项功能,文档数据可以保存到 iCloud 中,这样就可以在不同设备之间同步应用数据。  第 15 章:iOS 开发人员可以使用 Grand Central Dispatch 这种新方法进行多线程开发,它 还可以让应用必要时在后台运行。这一章将展示如何使用 Grand Central Dispatch 和后台 处理。  第 16 章:人们都喜欢画画,这一章介绍自定义绘图,我们将为你讲解 Core Graphics 的绘 图机制。  第 17 章:在 iOS 7 中,苹果引入了一个叫作 Sprite Kit 的新框架,用来创建 2D 游戏。它 包含了物理引擎和动画系统,也可以用来创建 OS X 系统上的游戏。在第 17 章中,你将 会看到如何使用 Sprite Kit 创建一个简单的游戏。  第 18 章:iOS 设备的多点触摸屏幕可以接受用户的各种手势输入。这一章讲述如何检测 基本的手势,如双指捏合和单指滑动,还将介绍如何以及何时应该自定义新手势。  第 19 章:iOS 可以通过 Core Location 确定设备所处的纬度和经度。本章中会编写一些使 用 Core Location 的代码,用于计算设备所在位置,并且使用位置信息来实现我们让世界 连通的理想。  第 20 章:讨论如何与 iOS 的加速计和陀螺仪进行交互,通过它们可以确定设备的握持方 式、运动速度,以及移动方向、设备所在位置。我们也会研究应用使用这类信息可以做 哪些有趣的事情。  第 21 章:每台 iOS 设备都有自己的摄像头和照片库,获得用户允许之后,你的应用程序 就可以访问摄像头和照片库。这一章介绍如何在自己的应用程序中使用它们。  第 22 章:iOS 设备现已遍及 90 多个国家。本章会介绍如何把应用的各个部分恰当地翻译 为其他语言,这样有助于发掘应用的潜在用户。  至此,你已经掌握了 iPhone 和 iPad 应用的基本构建方法。附录将给出一些精通 iOS SDK 需要关注的其他资源。 1.5 这一版的新内容 自本书第 1 版上市以来,iOS 开发社区也取得了巨大发展。苹果不断更新 SDK,使它持续发 展完善。 当然,我们也很忙。iOS 7 增强了许多新的功能并改变了显示内容的方式。Xcode 5 也添加了 许多强大的功能,Interface Builder 还更好地改善了对自动布局机制的支持,采用了新的图片资源 管理方式,全面地使用分镜(storyboard)来代替所有旧的 nib 项目模板(不过需要注意的是,nib 文件以及使用了它的项目仍然可以正常运行,以后的版本也一样)。我们竭尽全力地更新章节内 容,使本书能完整地覆盖所有这些新的技术。每个项目都是我们从头开始重新构建的,以确保项 目的代码不但能在最新版的 Xcode 和 iOS SDK 下编译,而且还能够充分利用 Cocoa Touch 提供的 强大新功能。这一版内容进行了大量细微调整,也添加了许多实质性变动,包括新增一章内容用 1.6 准备开始吧 9 1 2 3 4 5 11 6 7 8 9 10 来讲述 Sprite Kit 游戏框架。当然我们也对本书中的所有屏幕截图进行了更新。 1.6 准备开始吧 iOS 是一个不可思议的计算平台,是令人兴奋的新领域,令开发充满乐趣。编写 iOS 程序不 同于为其他任何平台开发应用程序,将成为一种全新的体验。所有看似熟悉的功能都具有其独特 之处,但只要深入理解本书中的代码,就能把这些概念紧密联系起来,并融会贯通。 应该谨记,完成本书中的所有练习并不能立即成为 iOS 开发专家。在进行下一个项目之前, 请确保你已经完全理解了已完成的项目。不要害怕修改代码,熟悉 Cocoa Touch 这种编程环境的 最佳方法就是不断实验并观察结果。 如果你已经安装了 iOS SDK,请继续阅读本书;如果还没有,请立即安装。明白吗?好,开 始动手吧! 10 第2 章 创建项目 创建项目 你可能知道,任何编程书都习惯使用“Hello, World!”作为第一个项目的名称,这已然成为 一种传统。我们曾考虑过打破这种常规,但又恐标新立异犯了众怒。因此,本书也以“Hello, World!”作为第一个项目。 本章将使用 Xcode 创建一个小型 iOS 应用,在模拟设备屏幕上显示文本“Hello, World!”。 我们将讨论使用 Xcode 创建 iOS 应用的各方面内容,深入探究使用界面构建器设计应用用户界面 的具体细节,最后在 iOS 模拟器上运行应用。随后,将为应用指定一个图标,让它看起来更像真 正的 iOS 应用。 要做的事情很多,开始吧。 2.1 在Xcode 中创建项目 现在,你应该已经在机器上安装了 Xcode 和 iOS SDK。还应该从本书的网站(http://www. learncocoa.com)下载本书的项目归档文件。还可以顺便看一下本书的论坛(http://forum. learncocoa.org/)。本书的论坛是讨论 iOS 开发的好地方,你可以在这里提问,还能够结交到志同 道合的朋友。 注意 即使你已经拥有了本书的完整项目文件,这里仍然建议你亲自动手创建每一个项目,而不 是直接运行下载到的项目文件。只有通过实践,才能更好地熟悉并精通各种应用开发工具。 软件开发可不是只靠观察就能学好的,除了亲自动手创建应用,别无他法。 在本书项目归档的 02-Hello World 文件夹中,可以找到本章要创建的项目。 在开始之前,需要启动 Xcode。本书中大部分编程工作都要使用 Xcode 完成,从 Mac App Store 下载到 Xcode 之后,你会发现 Xcode 与大多数 Mac 应用一样安装到了/Applications 文件夹下。因 为要经常用到 Xcode,所以可以将它的图标拖到 Dock 上,以方便使用。 如果是第一次使用 Xcode,也不用担心,我们将详细介绍创建新项目的每一步骤。如果你很 熟悉以前版本的 Xcode,但是还没用过 Xcode 5,就会发现有很多变化(大多是变得比旧版更好了)。 第一次启动 Xcode 时,会显示如图 2-1 所示的欢迎窗口。从这里可以创建一个新的项目,可 第2章 2.1 在Xcode 中创建项目 11 1 2 3 4 5 11 6 7 8 9 10 以连接到版本控制系统,检查已有项目,还可以从最近打开的项目列表中选择一个项目。欢迎窗 口为新手提供了一个非常好的入门指南,它把最常见的一些任务列了出来。所有这些功能都可以 在 Xcode 菜单里找到。浏览完成之后关闭这个窗口,继续学习其他内容。如果不希望再次看到这 个窗口,只需在关闭该窗口前取消勾选底部的 Show this window when Xcode launches(当 Xcode 加载时显示该窗口)选项就可以了。 图 2-1 Xcode 欢迎窗口 注意 如果你的 Mac 机器连接了 iPhone、iPad 或者 iPod touch 等设备,那么第一次启动 Xcode 时可能会看到一个对话框,询问你是否要使用该设备进行开发。就目前的学习来说,点 击 Ignore(忽略)按钮就可以了。否则就会显示 Organizer(组织者)窗口,列出与机器 同步的设备。这种情况下,直接关闭 Organizer 窗口即可。如果已经加入了付费的 iOS 开 发者计划(iOS Developer Program),那么你就能访问苹果的应用开发者计划网站,了解 如何使用 iOS 设备进行开发和测试。 要创建新项目,可以选择 File➤New➤Project...(或者按下 shift+command+N)。这时会看到 一个新建项目窗口,其中显示了项目模板选择面板(参见图 2-2)。可以从这个面板中选择一个项 目模板作为构建应用的起点。窗口左侧的面板分为两个主要部分:iOS 和 OS X。由于我们要创 建的是 iOS 应用,所以选择 iOS 部分的 Application(应用)类别,以显示 iOS 应用模板。 图 2-2 右上方面板中的每一个图标都表示一个独立的项目模板,这些模板可以用作构建 iOS 应 用的基础。Single View Application(单视图应用)是最简单的模板,本书前几章将会用到它。而其 他模板提供了额外的代码和资源来创建一些通用的 iPhone 和 iPad 应用界面,这些将在后面的章节 介绍。 单击 Single View Application 图标(如图 2-2 所示),然后单击 Next 按钮,就会看到项目选 项表单,如 图 2-3 所示。在这个表单中,需要为项目指定 Product Name(产品名称)和 Company Identifier(公司标识)。Xcode 会将这些内容结合起来,为应用生成一个唯一的 Bundle Identifier 12 第2 章 创建项目 (包标识符)。还可以看到一个 Organization Name(组织名称)字段,Xcode 会自动在你创建的 每一个源代码文件中以这个名称插入版权声明。把 Product Name 设置为 Hello World,组织名 称为 Apress,然后在 Company Identifier 字段填写 com.apress,如图 2-3 所示。等你注册了开发 者计划并且了解授权文件(provisioning profile)之后,就可以使用自己的公司标识了。本章稍 后将会更详细地讨论包标识符。 图 2-2 创建项目时,可以从项目模板选择面板列出的模板中选择一个 图 2-3 为项目选择 Product Name 和 Company Identifier。目前使用如图所示的设置 下一个文本框标是 Class Prefix(类名前缀),这里应该输入一个至少包含 3 个大写字母的字 符串。这个字符串会被添加到 Xcode 为我们创建的所有类的类名前面。这么做是为了避免与苹果 (使用两个字符的前缀)以及可能会用到的其他开发者的代码发生命名冲突。在 Objective-C 中, 2.1 在Xcode 中创建项目 13 1 2 3 4 5 11 6 7 8 9 10 两个类同名会导致应用构建失败。 本书的项目将使用 BID 作为前缀,BID 代表 Beginning iOS Development。例如,可能有很多 类会被命名为 MyViewController,然而被命名为 BIDMyViewController 的类就很少了,这就大大 降低了命名冲突的可能性。 我们还需要设置 Devices(即设备类别)的值。也就是说,Xcode 需要知道我们要创建的应 用究竟是用于 iPhone、iPod touch,还是 iPad,或是能够在所有 iOS 设备上运行的通用应用。在 设备类别中选择 iPhone(如果它还没有被选中)。这就告诉 Xcode 我们将创建的这个应用专用于 iPhone 和 iPod touch(它们的屏幕尺寸相同)。本书第一部分将始终使用 iPhone 作为设备类别, 不过不用担心,后面会介绍 iPad 开发。 再次单击 Next 按钮,此时会看到一个标准的保存对话框,要求指定项目的保存位置,如图 2-4 所示。如果你尚未为本书的项目创建一个新的主目录,那就先转到 Finder 创建一个,然后回 到 Xcode,切换至该目录。点击 Create按钮之前,先注意一下 Create local git repository for this project (创建该项目的本地 git 仓库)选项。本书不打算讨论 Git,但是 Xcode 内置了对 Git 和其他版本控 制系统的支持。如果比较熟悉 Git 并且希望在项目中使用它,就选中这个选项,否则就不要选中。 注意 版本控制系统(Source Control Management,简称 SCM)这个技术用于在构架应用时跟 踪代码变更和资源变更。它提供了一些工具,可以解决多个开发者同时更改某一个应用 时可能引起的冲突问题。Xcode 已经内置了对 git(当今最流行的版本控制系统)的支持。 本书不使用版本控制系统,所以是否要勾选这个选项取决于你,选不选都可以。 无论是否勾选了 git 版本控制,点击 Create 按钮之后都会创建一个新的项目出来。 图 2-4 将项目保存到硬盘上的某个项目文件夹中 14 第2 章 创建项目 2.1.1 Xcode项目窗口 确定项目的保存路径之后,Xcode 就会创建并打开项目。这时会看到一个新的项目窗口,如 图 2-5 所示。该窗口包含许多信息,它也是进行 iOS 开发用到的主要窗口。 图 2-5 Xcode 中的 Hello World 项目 即使你非常熟悉旧版的 Xcode,阅读本节内容仍然会有很多收获,因为在这里介绍了很多 Xcode 5 上的新功能,相比 Xcode 3.x 和 Xcode 4.x,又发生了很多变化。我们简单了解一下。 1. 工具栏 Xcode 项目窗口的顶部区域是工具栏(图 2-6)。工具栏左侧依次是用于启动和停止项目运行 的控制按钮、用于选择运行方案的下拉菜单,以及用于启用和禁用断点的按钮。方案(scheme) 将目标和构建设置结合在一起。通过工具栏上的下拉菜单,开发者只需点击一次就能选择一种特 定的设置。 图 2-6 Xcode 工具栏 2.1 在Xcode 中创建项目 15 1 2 3 4 5 11 6 7 8 9 10 工具栏中间的大方框是活动视图(activity view)。顾名思义,活动视图显示着当前正在进行 的操作或处理。例如,运行项目时,活动视图会显示应用构建过程中每一步的运行时说明。如果 出现了错误或者警告,这些信息也会显示在活动视图中。如果点击其中的警告或错误,就会直接 跳转到问题导航面板,问题导航面板提供了更为详细的警告和错误信息,下一节将会介绍这部分 内容。 在工具栏右侧有两组按钮。左侧的一组按钮可以在三种不同的编辑器配置间进行切换。  标准编辑器(standard editor)提供了一个面板,用于编辑文件或者编辑项目相关的配置 数值。  辅助编辑器(assistant editor)非常强大,它将编辑器面板分割为左右两个部分。右侧面 板通常用于显示左侧面板中文件的关联文件,或者是你在编辑左侧文件时可能会用到的 文件。可以手动指定每个面板的内容,也可以让 Xcode 自动判断进而显示与当前任务匹 配度最高的内容。例如,如果你正在编辑一个 Objective-C 类的实现文件(.m 文件),Xcode 就会自动在右侧面板中显示这个类的头文件(.h 文件)。如果你正在左侧面板中设计用户 界面,Xcode 就会在右侧面板中显示能够与这个用户界面进行交互的代码。本书从头至尾 都在使用辅助编辑器。  版本编辑器(version editor)按钮将编辑器面板转换为一个与 Time Machine 类似的对比视 图,这个对比视图可以跟 Subversion 和 git 等版本控制系统协同工作。可以将一个源文件 的当前版本与之前提交的版本进行比较,或者对任意两个之前的版本进行比较。 编辑器按钮的右侧是另一组开关,用于控制左侧的面板、右侧编辑器视图以及项目窗口底部 的调试区域的显示与隐藏。动手点击这些按钮几次,试试这组开关的功能。你很快就要学习如何 使用这些按钮了。 2. 导航视图 工具栏下方,项目窗口左侧就是导航视图(navigator)。如果你之前曾使用导航视图开关把 它隐藏的话,请再次将其显示出来。导航视图共提供了 8 个面板,供开发者以不同的方式查看 项目。点击导航视图顶部的图标可以在不同类型的导航面板中进行切换。下面从左至右依次介 绍它们。  项目导航面板(project navigator):这个面板列出了项目用到的所有文件,如图 2-7 所示。 可以把任何想要的内容引用放在这里,从源代码文件到图片文件、数据模型、属性列表 文件(也叫 plist 文件,2.1.2 节会介绍),甚至是其他项目文件。在一个工作区中存放多个 项目便于项目之间共享资源。在项目导航面板中点击任意一个文件,该文件都会在编辑 器面板中显示。不仅能查看文件,还可以编辑(只要 Xcode 知道如何编辑这种文件)。 16 第2 章 创建项目 图 2-7 Xcode 项目导航面板。通过单击导航视图顶部的 8 个图标, 就可以在不同的导航面板之间切换  符号导航面板(symbol navigator):顾名思义,这个导航面板集中了所有在工作区中定 义的符号(symbol),如图 2-8 所示。从根本上说,符号就是那些编译器能识别的东西, 例如 Objective-C 类、枚举类型、结构体和全局变量。 图 2-8 Xcode 符号导航面板。点击倒三角按钮可以看到每个分组中 定义的文件和符号  搜索导航面板(Find navigator):使用这个导航面板可以对工作区中的所有文件执行搜索, 如图 2-9 所示。面板顶部有多层下拉菜单,Find(查询)功能也可以改成 Replace(替换) 2.1 在Xcode 中创建项目 17 1 2 3 4 5 11 6 7 8 9 10 功能,此外还可以对输入的文本采用不同的搜索方式。在文本框下方的其他控件可以让 你选择搜索范围是整个项目还是其中一部分,或指定是否区分字母大小写。 图 2-9 搜索导航面板。记得查看一下 Find 文本中和位于搜索框 下面的按钮上的隐藏下拉菜单  问题导航面板(issues navigator):构建项目过程中出现的任何错误或者警告都会在这个 导航面板中显示,同时窗口顶部的活动视图中会显示错误数量,如图 2-10 所示。点击问 题导航面板中的任一错误,就会跳转到编辑器面板中相应的代码行。 图 2-10 问题导航面板。可以在这里找到编译错误和警告 18 第2 章 创建项目  测试导航面板(Test navigator):如果你正在使用 Xcode 内置的单元测试功能(很遗憾, 本书不会深入介绍这方面的内容),那么你将会在这里看到测试的结果(如图 2-11 所示)。 图 2-11 测试导航面板。单元测试的打印结果将显示在这里  调试导航面板(debug navigator):这个导航面板是观察调试过程的主要区域,如图 2-12 所示。如果你对调试很陌生,可以查阅 Xcode 5 User Guide 文档的相关部分,网址是: http://developer.apple.com/library/mac/#documentation/ToolsLanguages/Conceptual/Xcode4Us erGuide/060-Debug_Your_App/debug_app.html。 图 2-12 调试导航面板。建议试用一下窗口底部的细致程度滑块, 可以通过它指定想要查看的调试细节 调试导航面板列出了每个活动线程的栈帧。栈帧(stack frame)按调用顺序列出了之前调 用过的函数或方法。点击某个方法,与之对应的代码就会显示在编辑器面板中。在编辑 2.1 在Xcode 中创建项目 19 1 2 3 4 5 11 6 7 8 9 10 器中,还有另一个面板,可以用来控制调试过程,显示和修改数据值以及访问底层调试 器。调试导航面板底部还有一个滑块,可以控制调试跟踪的细致程度。滑动到最右边可 以看到所有内容,包括所有的系统调用;滑动到最左边的话就只能看到自己的调用了。 默认位置为正中间,这是个不错的位置。  断点导航面板(breakpoint navigator):可以在断点导航面板中查看已设置的所有断点, 如图 2-13 所示。顾名思义,断点会指向导致应用停止运行(或者跳出)的代码部分,这 样就可以查看变量中的值,做一些别的工作来调试应用。这个导航面板中的断点列表是 以文件的形式组织的。在列表中点击一个断点,编辑器面板中就会显示该断点所对应的 代码行。位于断点导航面板时,记得查看一下项目窗口左下角的弹出菜单。可以通过加 号弹出菜单添加异常断点或者符号断点,也可以通过减号弹出菜单删除选定的断点。 图 2-13 断点导航面板。断点列表以文件的形式进行组织  日志导航面板(log navigator):这个导航面板中保存着构建结果和运行日志的历史记录, 如图 2-14 所示。点击某条日志,编辑器面板就会显示相应的构建指令和构建问题。 图 2-14 日志导航面板。它显示了一个项目运行列表,选中某项后,编辑器面板中就 会出现对应的详细信息日志 20 第2 章 创建项目 3. 跳转栏 在编辑器的顶部,你会找到一个叫作跳转栏(jump bar)的特殊控件,你只需要单击一次, 就能跳转到当前导航层次结构中的特定元素。例如,图 2-15 显示了一个正在编辑器面板中进行 编辑的源代码文件。跳转栏就在源代码上方,它有以下几个组成部分。  最左侧有一个看起来很特别的图标,它实际上是一个弹出菜单,可显示的子菜单包括最 近的文件(Recent Files)、未保存的文件(Unsaved Files)、关联文件(Counterparts)、父 类(Superclasses)、子类(Subclasses)、兄弟类(Siblings)、类别(Categories)、引用头 文件(Includes),等等,通过子菜单可以看到所有与编辑器当前文件相关的其他代码。  弹出菜单图标的右边是一对左右箭头,分别可以跳转到上一个文件和下一个文件。  跳转栏包含一组分段式的弹出菜单,显示了在项目中找到当前所选文件的层级路径。你可 以试着点击任意一个显示了组或文件名称的分段按钮,来查看位于同一层级的所有其他文 件和组。最后一个分段按钮展示了当前所选文件中各项内容的列表。在图 2-15 中,你可以 看到跳转栏最右边的弹出菜单显示了当前文件包含的所有方法和用符号代表的其他内容。 跳转栏当前显示的文件是 BIDAppDelegate.m,弹出菜单列出了该文件中定义的各项符号。 图 2-15 Xcode 编辑器面板显示的跳转栏,编辑器面板中则显示了跳转栏中选择的 源代码文件。跳转栏的弹出子菜单列出了当前文件的所有方法 跳转栏是非常强大的。在查看 Xcode 5 的各种界面元素时一定要注意它。 提示 与大部分的 OS X 应用一样,Xcode 5 也支持全屏显示功能。点击项目窗口右上角的全屏 按钮,感受一下不会分散注意力的全屏编码模式吧! Xcode 键盘快捷键 如果你喜欢使用键盘快捷键进行导航,而不是使用鼠标进行屏幕控制的话,那么你肯定会 喜欢 Xcode 提供的快捷键。Xcode 中的大部分常用操作都有对应的快捷键,比如 command+B 2.1 在Xcode 中创建项目 21 1 2 3 4 5 11 6 7 8 9 10 可以构建应用,command+N 可以创建新文件。 可以自由更改所有的 Xcode 快捷键,也可以在 Xcode 首选项的 Key Bindings 标签中为未 指定快捷键的命令指定一个快捷键。 一个非常好用的快捷键是 shift+command+O,对应的是 Xcode 的 Open Quickly 功能。按下 该快捷键后,键入一个文件名、设置项名称或者符号名,Xcode 就会显示一个选项列表。找到 想要的文件后按下 return 键就可以在编辑器面板中打开这个文件,这样只需要进行几次键盘操 作就能够快速切换文件。 4. 实用工具面板 之前提到,Xcode 工具栏右侧倒数第二个按钮用于打开、关闭实用工具面板。和检查器面板 类似,实用工具区域是一个上下文相关的检查器面板,它的内容会随着编辑器面板的显示内容而 变化。实用工具区域的下方显示了一些不同类型的资源,你可以将它们拖动到你的项目中。本书 有很多这样的例子。 5. 界面构建器 Xcode 的早期版本包含一个被称为界面构建器(Interface Builder)的界面设计应用,用于在 项目中构建和自定义用户界面。后来,Xcode 就把界面构建器集成到了工作区中。界面构建器不 再是一个独立的应用了。这就意味着,在编写代码和设计界面时,不需要在 Xcode 和界面构建器 之间反复切换了。这个功能变化已经是很多年前的事情了,不过对于包括我们在内,那些经历过 独立版界面构建器应用日子的人来说,现在的界面构建器能直接集成到 Xcode,确实是件让人觉 得非常愉悦的事情。 本书中的例子会大量使用 Xcode 的界面创建功能,并深入探讨其中的细节。事实上,本章稍 后就会创建我们的第一个界面。 6. 新的编译器和调试器 Xcode 4 最重要的变化之一是内部机制的变化:一个全新的编译器(compiler)和底层调试器 (low-level debugger)。它们都比之前更快更智能。 过去几年苹果一直使用 GCC(GNU C Compiler)作为底层编译器。不过最近几年,苹果已 经全面转换到新的 LLVM(Low Level Virtual Machine,底层虚拟机)编译器。LLVM 的代码生成 速度远比传统的 GCC 快。除了代码生成速度快之外,LLVM 还知道更多与代码相关的信息,所 以它能生成更智能、更精确的错误信息和警告。 Xcode 对 LLVM 也有很好的集成,后者为前者注入了强大的能量。Xcode 可以提供精确的代 码补全功能,而且当要产生警告或者弹出修复建议菜单时,它可以对代码片段的实际意图作出更准 确的猜测。这样就可以很容易地找到并修正符号名称拼写错误、括号匹配错误、分号遗漏等问题。 此外,LLVM 还提供了一个复杂的静态分析器(static analyzer),它可以扫描你的代码以查 找各种潜在问题,包括 Objective-C 的内存管理问题。事实上,LLVM 在这方面确实相当智能, 它可以为你处理大多数内存管理任务,不过前提是编写代码时要遵守一些简单的规则。下一章开 始讨论之前提到过的 ARC(自动引用计数)功能。 22 第2 章 创建项目 2.1.2 深入研究项目 我们已经讨论了 Xcode 项目窗口,现在来看看 Hello World 项目中的文件。单击 8 个导航面 板图标(位于工作区左侧)中最左边的那个图标(参见本章前面的“导航视图”一节)或者按下 command+1,切换到项目导航面板。 提示 可以用 command+1 到 command+8 之间的快捷键在 8 个导航面板之间进行切换。从最左 边的图标开始,数字与图标排序一一对应,所以,command+1 对应项目导航面板, command+2 对应符号导航面板,以此类推,command+8 对应日志导航面板。 项目导航面板中的第一个条目就是项目名,本例为 Hello World。这个条目表示整个项目, 可以做些与项目相关的配置。单击这个条目,就可以在 Xcode 的编辑器中编辑项目的很多配置 项。不过现在不用担心那些与具体项目相关的设置。目前来说,保留默认设置即可。 回过头来看一下图 2-7。Hello World 左侧的倒三角是展开的,下面显示了如下一些子文件夹 (在 Xcode 中称为组)。  Hello World:这是第一个文件夹,它总是以项目名来命名,你会把大量时间花在这个文 件夹上。它包含了应用的大部分代码以及用户界面文件。可以在这个文件夹下随意创建 子文件夹,从而更好地组织代码,甚至可以使用其他分组代替这个默认的文件夹(如果 你想换个方式组织代码的话)。这个文件夹中的大部分文件都将留到下一章再介绍,但是 有一个文件在下一节使用界面构建器时会用到,下一小节就会加以介绍。  Main.storyboard:这个文件包含了项目主视图控制器用到的用户界面元素。  Supporting Files:Hello World 文件夹内的某个文件夹,包含了项目中必需的非 Objective-C 类的源代码文件和资源文件。通常,不会在 Supporting Files 文件夹上花费太多时间。创 建一个新的 iPhone 应用项目后,这个文件夹就会包含 4 个文件。  Hello World-Info.plist:这是一个属性列表,包含应用相关的各种信息。2.3 节会简单介 绍这个文件。  InfoPlist.strings:这是一个文本文件,包含可能被信息属性列表引用到的可读字符串。 不同于信息属性列表,这个文件可以被本地化,这样就能在应用中包含多种语言(第 21 章会介绍这个话题)。  main.m:这个文件包含应用的 main()方法。通常不需要编辑或修改这个文件。事实上, 最好不要碰这个文件,除非你真的知道自己在做什么。  Hello World_Prefix.pch:这个文件包含项目中用到的所有外部框架的头文件(扩展名.pch 代表 precompiled header,意思是预编译头文件) 。通常,这个文件中包含的头文件并不 是项目的一部分,也不会经常更改。Xcode 会预先对这些头文件进行编译,之后构建应 用时就直接使用预编译过的版本,这样就减少了编译项目所需的时间(点击 Build 或 Run 可以对项目进行编译) 。暂时不需要关心这个文件,因为它已经包含了最常用的头文件。 2.2 界面构建器简介 23 1 2 3 4 5 11 6 7 8 9 10  Hello WorldTests:如果你想要为你的应用编写一些单元测试代码,这个文件夹就会包含 所需的初始化文件。我们不会在本书中讲解单元测试的内容,但是你创建的每个项目 Xcode 都会替你设置好这些事情,这点很不错。与 Hello World 文件夹类似,它也包含了 自己的 Supporting Files 文件夹,里面是构建并运行单元测试代码必须用到的文件。  Frameworks:框架是一种特殊的库,其中可以包含代码,也可以包含图像和声音之类的 资源。添加到 Frameworks 文件夹中的框架或者库都会被链接到应用,这样你的代码就可 以使用这些框架或库中的类、函数和其他资源。最常用的框架和库默认都会被链接到项 目中,所以大多数情况下不必向这个文件夹添加任何东西。如果确实需要使用那些不常 用的库和框架,可以很容易地把它们添加到 Frameworks 文件夹中。第 7 章将介绍如何添 加框架。  Products:这个文件夹包含构建项目时生成的应用。展开 Products 文件夹,可以看到一个 名为 Hello World.app 的文件,这就是这个项目创建出来的应用。它还包含了一个名字为 Hello WorldTests.xctest 的文件,它表示测试代码。这些文件都被称为构建目标(build target)。由于我们还没有构建这个应用,所以它们都显示为红色,Xcode 利用这种方式告 诉你这个文件并不存在。 注意 导航面板区域中的“文件夹”并不一定与 Mac 文件系统上的文件夹一一对应。它们只是 Xcode 中的逻辑分组,用于对所有的东西进行组织,以便在应用开发时可以更快更容易 地找到需要的内容。通常,这两个项目文件夹中的文件都直接保存在项目目录下,但是 也可以把它们保存到其他位置,如果你愿意的话,甚至可以把它们放到项目文件夹外部。 Xcode 内部的层次结构与文件系统的层次结构完全无关,比如,在 Xcode 中把一个文件 移出 Classes 文件夹并不会改变这个文件在硬盘上的位置。 使用实用工具面板可以对分组进行配置,可以为这个分组分配一个具体的文件系统目录。 但是,默认情况下,项目中新加入的分组完全独立于文件系统,这些分组的内容可以保 存在任何地方。 2.2 界面构建器简介 在项目窗口的项目导航面板中展开 Hello World 组(如果尚未展开),然后选择 Main.storyboard 文件。然后这个文件就会在编辑器面板中打开(参见图 2-16)。你将在纯白色背景的中央看到一 个完全空白的 iPhone 屏幕,可以在这个背景上编辑界面。这就是 Xcode 的界面构建器(有时被 称为 IB),可以在这里设计应用的用户界面。 界面构建器历史悠久,它于 1988 年面世,曾用于开发 NeXTSTEP、OpenStep、Mac OS X 应 用,现在也用于 iPhone 和 iPad 等 iOS 设备。之前已经提到过,界面构建器过去曾是一个独立的 应用(安装 Xcode 时会自动安装界面构建器),它与 Xcode 协同工作。而现在,界面构建器被完 全集成到了 Xcode 中。 24 第2 章 创建项目 图 2-16 在项目导航面板中选择 Main.storyboard。这将在界面构建器中打开该文件。 它看起来应该会是这样的 2.2.1 文件格式 界面构建器支持不同的文件类型:最初的版本使用扩展名为 nib 的二进制格式,后来改用扩 展名为 xib,这是一种基于 XML 的衍生格式。两者包含了完全一样的文档内容,但 xib 格式的版 本却是基于文本格式的,这样做有很多优势,尤其是在你使用版本控制系统的时候。 注意 iOS 项目模板全都默认使用.xib 扩展名,但是在最初的 20 年里,所有的界面构建器文件 都使用.nib 扩展名,结果就是大部分开发者都把界面构建器文件称为“nib 文件”。不管文 件实际使用的是.xib 扩展名还是.nib 扩展名,都被称为“nib 文件”。事实上,苹果公司仍 然在其文档中使用“nib”和“nib 文件”这两个术语。 一个 nib 文件可以包含任意数量的对象。但在 iOS 项目中,通常每个 nib 文件负责包含一个 视图(一般都是全屏视图)以及相关联的控制器或对象。用这种方式对应用进行划分,只在某个视 图需要显示的时候加载它的 nib 文件。这样做能为内存受限制的 iOS 设备节约应用运行时的内存。 2.2 界面构建器简介 25 1 2 3 4 5 11 6 7 8 9 10 最近几年,界面构建器开始支持另一种文件类型,即分镜(storyboard)。你可以将分镜想像 成一个“元 nib 文件”(meta-nib file),因为它可以包含多个视图和控制器,以及如何在应用运行 时进行相互连接的配置信息。与一次就加载完所有内容的 nib 文件不同,分镜不会一次加载所有 的内容,而是在你需要加载某视图和控制器时向它请求特定内容。 在本书中,分镜和 nib 文件我们都会使用到。在当前的示例中,Xcode 为我们创建了一个分 镜,所以我们先来看看它的用法。 你现在研究的是将来构建 iOS 应用用户界面的首选工具。现在,假设你想创建一个按钮实 例。你可以通过编写代码来创建这个按钮,不过更简洁的方法是从库中拖出一个按钮用来创建界 面对象并指定它的各项属性,这与在运行时创建的按钮完全一样。 Main.storyboard 文件会在应用启动时自动进行加载(目前不需要关心这是如何实现的),往 这里添加对象就可以组成应用的用户界面。在界面构建器中创建的对象会在程序加载分镜或 nib 文件时被实例化。本书有很多这样的例子。 2.2.2 分镜 每个分镜都是由一组或多组相对应的视图和控制器构成的。视图就是你眼睛能看到并可以在 界面构建器中进行编辑的部分,而控制器则是你编写的应用代码,用来处理用户的交互事件。应 用的实际操作都是在控制器内执行的。 在界面构建器中,你经常会看到一个表示 iPhone 屏幕尺寸(虽然也可能是其他尺寸)的矩 形视图,我们当前的示例也同样如此。点击矩形的任意位置,你将看到底下一行出现了三个图标。 把鼠标悬停在每个图标上面,你会看到弹出的工具提示显示了它们各自的名称:View Controller (视图控制器)、First Responder(第一响应者)和 Exit(离开)。目前请先忽略掉 Exit,把注意力 集中到更重要的两项上。  视图控制器代表会从某存储文件中加载控制器以及相关联的视图。  第一响应者简单地说,就是用户当前正在进行交互的对象。如果用户正在向一个文本框 中输入数据,那么这个文本框就是当前的第一响应者。第一响应者会随着用户与用户界 面的交互而变化,而通过 First Responder 图标则可方便地与当前作为第一响应者的控件等 对象进行通信,不需要编写代码来判断到底哪个控件(或视图)是当前第一响应者。 从下一章开始会详细介绍这些对象,所以你现在不必担心搞不清楚何时使用第一响应者以及 视图控制器是如何加载的。 除了这些图标以外,你在编辑区能看到的其余部分就是用来放置图形对象的空白区域。不过 在了解它之前,你需要注意界面构建器的编辑器中还有一个层级视图区域。点击编辑区左下角的 小按钮,你将会看到层级视图从左侧滑动出来。这里显示分镜的所有内容,并由相关的场景 (scene)作为容器来进行划分。在本示例中只有一个场景,它的名称是 View Controller Scene。你 会看到它包含了一个名称为 View Controller 的子项,往下依次又包含了一个名称为 View 的子项 (还有其他一些内容,你将在后面学到)。通过这种方式可以很方便地浏览全部的内容。你在主编 辑区域看到的所有内容都能在这里找到。 26 第2 章 创建项目 View 图标代表 UIView 类的一个实例。UIView 对象是一块用户能够看到并与之交互的区域。 本例只有一个视图,所以这个图标代表这个应用中用户能够看到的全部内容。之后我们会创建更 为复杂的多视图应用。目前来说,就认为这是用户使用应用时能够看到的全部内容即可。 注意 从技术角度来说,这个应用实际上包含多个视图。屏幕上显示的所有用户界面元素(包 括按钮、文本框、标签等)都继承自 UIView。但是,本书使用的术语视图(view)仅仅 指 UIView 的实例,所以称本应用只有一个视图。 点击 View 图标,Xcode 会自动对我们之前所说的 iPhone 尺寸屏幕的矩形进行高亮。在这里 可以使用图形化的方式设计用户界面。 2.2.3 库 工作区右侧的实用工具视图被分为了两部分,如图 2-17 所示。如果没有看到这个实用工具 视图,可以单击工具栏上三个 View 按钮中最右边的那个,选择 View➤Utilities➤Show Utilities, 或者按下 option+command+0。 图 2-17 库包含了 UIKit 内置的各种对象,可以在界面构建器中使用它们。 库与工具栏之间的部分统称为检查器 实用工具视图的下半部分称为库面板(library pane),或者简称为库。库是可重用对象的集 合,可以在自己的程序中使用它们。库面板顶部工具栏中的 4 个图标将它分成了 4 个部分。  文件模板库(file template library):这部分包含一些文件模板,向项目中添加新文件时可 以使用它们。例如,如果要向项目中添加一个新的 Objective-C 类,就可以从文件模板库 中拖出一个 Objective-C 类文件。 2.2 界面构建器简介 27 1 2 3 4 5 11 6 7 8 9 10  代码片段库(code snippet library):这部分包含一些精选的代码片段,可以直接把它们拖 到源代码中使用。记不住 Objective-C 的快速枚举语法?没关系,就从库里拖出这个特定 的代码片段,不需要再去翻书了。写了一些希望以后能够再次使用的代码?在文本编辑 器中选中想要的代码,然后把它拖到代码片段库中就行了。  对象库(object library):这部分包含各种可重用对象,比如文本框、标签、滑块、按钮等 可以用来设计 iOS 界面的任何对象。本书的示例程序会大量使用对象库来创建界面。  媒体库(media library):顾名思义,这个库包括用户的所有媒体文件,有图片、声音和影 片文件等。 注意 对象库中的对象主要来自于 iOS 的 UIKit 框架,这个框架中包含的对象可用于创建应用 的用户界面。UIKit 在 Cocoa Touch 中的作用与 AppKit 在 Cocoa 中的作用相同。这两个框 架在概念上很相似,然而由于平台之间的差异,它们也存在很多明显的不同。不过, NSString、NSArray 等属于 Foundation 框架的类,是 Cocoa 和 Cocoa Touch 共有的。 注意库面板底部的搜索框。想找一个按钮控件?那就在搜索框里输入 button,这时库会只显 示名字中含有“button”的项。搜索完成后记得要清空搜索框。 2.2.4 在视图中添加标签 现在试着使用界面构建器。单击库顶部的对象库图标(看起来像个立方体)打开对象库。向 下滚动,在库中寻找 Table View。继续滚动,找到它了!哦,等等,有个更好的方法:只要在搜 索框里键入 Table View 就可以了,这不是更容易吗? 提示 按下快捷键 control+option+command+3 就能跳转到搜索栏,并且高亮显示搜索框的内容。 接下来你就可以输入想要查找的内容了。 在库中找到 Label。它大约位于列表的顶部。然后,把标签控件拖放到之前介绍过的视图中。 (如果在编辑器面板中看不到视图,就在界面构建器的 dock 中单击一下 View 图标。)当把光标移 到视图上面时,光标就会变成一个绿色的加号指示符(在 Finder 中它表示“我正在复制某些内容”)。 把标签拖到视图中央。标签位于视图中央时会看到两条蓝色的引导线,一条垂直、一条水平。标签 是否居中并不重要,重要的是知道引导线的存在。图 2-18 显示了在释放鼠标之前工作区的情况。 用户界面中的对象是按照层次关系存储的。大多数视图都可以包含子视图,当然也有例外, 按钮和其他很多控件就不能包含子视图。界面构建器很智能,如果一个对象不接受子视图,那就 无法把其他对象拖到它上面。 把标签直接从库里拖动到正在编辑的视图中,就能将其作为子视图添加到主视图(名为 View 的视图)中,当主视图显示在用户面前时子视图会自动显示出来。从库中将一个 Label 拖到 View 视图中,实际上是在应用主视图上添加了一个 UILabel 的实例作为子视图。 28 第2 章 创建项目 图 2-18 在库中找到标签并把它拖到视图中。注意,我们在库的搜索框里键入了 label, 从而限制了对象列表只显示名称中含有 label 的对象 现在我们来编辑这个标签,让它显示一些有意义的内容。双击刚才创建的标签,键入文本 Hello, World!。在标签外点击鼠标,然后再重新选中标签,重新把标签拖到视图中央,或是放到 屏幕上你希望的任何地方。 你知道吗?只要保存项目,这个应用就完成了!选择 File➤Save(或者按下 command+S)。 然后查看 Xcode 项目窗口左上方的弹出菜单,事实上它是一个多分段的控件。左侧用来选择编译 目标以及其他一些设置,不过我们需要注意的是右侧,你可以在这里选择想要运行的设备。点击 右侧按钮你将会看到可用的设备列表。如果你已经连接了任意 iOS 设备并做好准备的话,它就会 出现在列表顶端。不然只会看到一个无意义的 iOS Device 选项。在它下面有一整段标题为 iOS Simulator 的列表,里面列出了你可以在 iOS 模拟器中使用的所有型号的设备。选择 iPhone Retina (4 inch),这样我们的应用就可以在这个模拟器中以 iPhone 5 的配置运行了。如果参与了苹果公 司的付费 iOS 开发者计划,还可以尝试在真实的 iPhone 上运行应用。本书尽量只使用模拟器, 因为在模拟器中运行不需要任何费用。 准备好运行这个应用了吗?选择 Product➤Run(或者按下 command+R)。Xcode 会编译这个 应用并且在 iPhone 模拟器中启动它,如图 2-19 所示。 2.2 界面构建器简介 29 1 2 3 4 5 11 6 7 8 9 10 图 2-19 iPhone 中的“Hello, World!”程序 注意 在构建并运行应用时,如果已经有 iOS 设备连接到 Mac,情况可能会与上面讲的有所不 同。总而言之,如果想要在 iPhone、iPad 或者 iPod touch 上构建并运行应用,就必须注册 苹果公司的 iOS 开发者计划并支付一些费用,然后还要对 Xcode 做一些恰当的配置。加 入开发者计划后,苹果公司会提供一些必要的信息,指导你完成在真实设备上运行应用 的配置工作。不过,本书的大部分程序都能很好地在 iPhone 或者 iPad 模拟器中运行。 欣赏完你自己的作品后,就可以返回 Xcode 了。Xcode 和模拟器是两个互相独立的应用。 提示 检查完应用后,可以退出模拟器,但是可能随时需要再次启动它。如果让模拟器一直运行, 那么要求 Xcode 再次运行应用时,Xcode 就会询问是否要先终止当前正在运行的应用再启 动新的实例。如果这让你感到困惑,那就在每次测试完应用后退出模拟器吧。没人知道! 等一下!这就完成了?可是还没有编写代码呢!是的,已经完成了! 是不是很赞? 如果想要修改标签的某些属性(比如字号或者字体颜色),应该如何实现呢?要编写代码吗? 不需要!接下来就来看看修改属性是件多么容易的事。 2.2.5 属性修改 返回 Xcode,单击 Hello World 标签以选中它。现在把注意力转向库面板上方的区域。面板 30 第2 章 创建项目 的这一部分称为检查器。与库类似,检查器面板顶部也有一些图标,点击图标就可以切换检查器 以显示特定类型的数据。要改变标签的属性,可以点击左起第四个图标,这样就会切换到对象属 性检查器,如图 2-20 所示。 图 2-20 在对象属性检查器中查看标签属性 提示 检查器面板与项目导航面板类似,每个图标都有对应的键盘快捷键。option+command +1 对应检查器最左边的图标,option+command+2 对应第二个图标,以此类推。与项目导航 面板不同的是,检查器面板中的图标个数会根据在导航面板或编辑器中选择的对象而改变。 接下来根据自己的喜好来改变标签的外观。可以随意修改文本的字体、字号以及颜色。注意, 如果加大了字号,可能需要调整标签大小以容纳更大的文本。完成后,保存文件,再次选择 Run。 刚才所做的修改就会在应用中显现出来了,同样,这次也没有编写任何代码。 2.3 画龙点睛——美化 iPhone 应用 31 1 2 3 4 5 11 6 7 8 9 10 注意 不用太过担心对象属性检查器中所有字段的含义,如果某一项更改没有生效也不用着急。 在学习本书的过程中,能够学到很多对象属性检查器相关的内容,以及每个字段的作用。 界面构建器支持以图形化的方式设计用户界面,从而使你能够专注于编写具体应用的代码, 而不用花时间编写冗长的代码来构建用户界面。 大多数现代应用开发环境都提供了一些工具,支持以图形化的方式构建用户界面。界面构建 器与其他很多工具的一个区别就是,界面构建器不会生成任何需要手动维护的代码。事实上,界 面构建器创建的是 Objective-C 对象(与在代码中所做的一样),然后把这些对象序列化到分镜或 nib 文件中,以便在运行时把它们直接加载到内存中。这样做避免了很多与代码生成相关的问题, 总而言之,这是个更好更强大的方法。 2.3 画龙点睛——美化 iPhone 应用 现在只剩下最后一步,对应用进行美化,使它更像一个真实的 iPhone 应用。首先,运行项 目。模拟器窗口出现后,按一下 iPhone 的主屏幕(窗口底部带有白色方框的黑色按钮)。这样就 返回到 iPhone 的主屏幕了,参考图 2-21 中的内容。是不是觉得有点单调? 图 2-21 在项目资源目录中的 AppIcon 面板。可以在这里设置你的应用图标 看一下屏幕顶部的 Hello World 图标。这样的图标真是拿不出手,是吧?要解决这个问题, 需要创建一个图标并将它保存为.png(Portable Network Graphic,便携式网络图像)文件。事实 上,最佳的方案是创建两个图标。一个大小为 120 像素×120 像素,另一个为 80 像素×80 像素, 此外还需要 58 像素×58 像素。为什么要三个图标呢?第一个用来在 iPhone 的主屏幕上显示你的 应用。第二个会在 iPhone 上使用 Spotlight 搜索到应用时出现。第三个则显示在“设置”应用中。 如果你没有提供较小的图标,就会对大图标进行适当的缩放。不过为了最优效果,你(或者是你 团队中的美工)需要预先缩放好大小。 32 第2 章 创建项目 注意 图标尺寸的问题要更复杂一些,在 iOS 7 之前,所有 iPhone 的图标尺寸都是 114 像素× 114 像素。但如果还想支持老款的非视网膜屏的 iPhone,就还需要包含一个缩小一半的图 标,57 像素×57 像素。iPad 上的应用也存在这种问题,无论是否配置有视网膜屏,iOS 7 和早先的 iOS 系统所用的图标尺寸也不相同。所以,我们现在避免讨论这个问题,只针 对运行 iOS 7 的 iPhone 配置图标尺寸。 创建图标时不需要模仿 iPhone 上已有的图标风格,iPhone 会自动把图标调整为圆角矩形。 只需要创建一个普通的正方形图像。如果不想创建自己的图标,可以直接使用我们提供的一组图 标,它们位于项目归档文件 02-Hello World-icons 文件夹下,这些图片分别叫做 icon-120.png、 icon-80.png 和 icon-58.png。 注意 必须使用.png 图像作为应用的图标,实际上 iOS 项目中所有图像都应该使用这种格式。 Xcode 在构建应用时会自动优化.png 图像,这使.png 格式成为 iOS 应用中最快、最有效的 图像格式。尽管大多数其他的常用图像格式也可以正确显示,但是,除非理由特别充分, 否则都应该使用.png 文件。 设计完应用图标后,按下 command+1 打开项目导航面板,查看 Hello World 文件夹里面名字 为 Images.xcassets 的文件。它被称为资源目录(asset catalog),是 Xcode 5 的新特性。每个 Xcode 项目创建时都会默认生成一个资源目录,用来管理你的应用图标和其他图片。选中 Images.xcassets, 然后将注意力转向编辑器面板。 在编辑器面板左侧,可以看到一个白色的纵向列,列出了名为 AppIcon 和 LaunchImage 的两 个条目。确保选中 AppIcon 条目。你会看到左上角标出 AppIcon 的白色区域,以及与我们之前所 说的三个图标相对应的虚线框(参见图 2-21)。我们要把应用图标拖到这里。 每个图标下面都有一段文字来说明需要用到哪一种图片。也会告诉你所需的图标尺寸。不过 这里有一个误区:Xcode 显示给你的是点数尺寸,而不是像素尺寸。这里的点数(point)指的是 屏幕上特殊的尺寸。在旧的 iPhone 设备(iPhone4 之前的所有手机)以及 iPad 一代、iPad 2 和 iPad mini 上一点代表单个像素。而在其他 Retina 屏幕的设备上,一点表示的实际上是一个 2 像素×2 像素的格子。资源目录中使用写有 2×的标签来进行提示,不过也只是标签而已。如果要算出某 一项实际需要的尺寸,可以选中它并按下 option+command+4 在窗口右侧打开属性检查器。在此 处能够同时看到 size(单位还是点数)以及 scale 值。一部分图标在此处都会显示 2×。将尺寸与 缩放值相乘,你将得到实际需要的像素尺寸大小。分别查看 AppIcon 面板中的每一项,检查器都 会提供相关的详细信息。这些内容与我们之前所说的一致,但你永远不会知道苹果下一步打算做 什么。从开始印刷直到你阅读本书为止的这段时间,苹果可能又发布了一些奇妙的设备,也许会 增加所需要的图标。 把 icon-120.png 从 Finder 拖到标注为 iPhone App 的方框中(应该位于右侧)。这样就把 2.4 小结 33 1 2 3 4 5 11 6 7 8 9 10 icon-120.png 复制到项目中并将其设置为应用的图标了。接下来,再把 icon-80.png 拖到中间的方 框,把它设置为 Spotlight 的图标。最后拖动 icon-58 到左边的方框内,它将成为 iOS 7 中“设置” 程序中显示的图标。 现在,编译并运行应用。模拟器启动之后,按下带有白色方框的按钮回到主屏幕,现在可以 看到漂亮的新图标了(参见图 2-22)。如果想要看到更小的图标,请在主屏幕上向下轻扫以调出 spotlight 搜索文本框,并输入单词 Hello,你将会立即看到新的应用图标。 注意 如果想把旧的应用从 iOS 模拟器的主屏幕上清除,可以从 iOS 模拟器的应用菜单中选择 iOS Simulator➤Reset Content and Settings...。 图 2-22 现在应用有一个漂亮的图标了 2.4 小结 现在可以缓口气了。本章可能并没有做太多事情,但是也确实介绍了不少基础知识。你学习 了 iOS 项目模板,了解了如何创建应用,掌握了很多 Xcode 5 相关内容,也开始使用界面构建器 了,最后还学习了如何设置应用的图标。 但是,这个 Hello World 程序是一个完完全全的单向应用。我们只是向用户显示一些信息, 却没能得到任何用户输入。让我们进入下一章,看看如何在 iOS 设备上获取用户输入,并根据用 户输入进行相应的操作。准备好了吗?做个深呼吸,然后翻到下一页。 34 第3 章 实现基本交互 实现基本交互 上一章的 Hello World 应用程序很好地展示了如何使用 Cocoa Touch 进行 iOS 开发,但它缺少 了一个至关重要的功能——与用户交互。如果不能与用户交互,应用的功能会严重受限。 本章将编写一个稍微复杂一点儿的应用,它有两个按钮和一个标签,如图 3-1 所示。用户按下 一个按钮时,标签上的文本会相应地改变。这看上去是一个相当简单的示例,但它展示了在 iOS 应用中实现交互功能所需的关键概念。为了增加趣味性,本章还会介绍如何使用 NSAttributedString 类,通过这个类可以对很多 CocoaTouch 的 GUI 元素使用带样式的文本(styled text)。 图 3-1 本章将构建的简单应用程序,它有两个按钮 3.1 MVC 方法 在深入学习之前,先介绍一些基本理论。Cocoa Touch 设计者们采用 MVC 模式(Model-View- 第3章 3.2 创建项目 35 1 2 3 4 5 11 6 7 8 9 10 Controller,模型视图控制器)作为指导原则。在基于图形用户界面的应用程序中,使用 MVC 可以非常合乎逻辑地对代码进行拆分。目前,几乎所有面向对象编程框架都在一定程度上借鉴了 MVC 的设计理念,但很少有像 Cocoa Touch 这样忠实于 MVC 的。 MVC 模式把代码功能划分为 3 个不同类。  模型:保存应用程序数据的类。  视图:包括窗口、控件以及其他一些用户可以看到并能与之交互的元素。  控制器:把模型和视图绑定在一起的代码,包括处理用户输入的应用程序逻辑。 MVC 的目标是最大限度地分离这 3 类代码。创建的任何对象都应该非常清晰明确,让人一 看便知这个对象所属的分类(模型、视图或控制器),尽量不要包含那些可能被认为属于多个分 类的功能。例如,实现按钮的对象不应该包含按钮点击时处理数据的代码,实现银行账户的对象 不应该包含绘制表格以显示交易数据的代码。 MVC 可以帮助确保代码的最大可重用性。一个实现通用按钮的类可以在任何应用程序中使 用,否则,如果实现按钮的类要在点击按钮时进行一些特定计算,那这个类就只能在最初实现它 的应用程序中使用。 编写 Cocoa Touch 应用程序时,主要使用界面构建器以可视化的方式创建视图组件,但有时 仍然需要在代码中修改(甚至创建)用户界面。 创建模型时,可以编写一个 Objective-C 类,保存应用程序数据,也可以使用 Core Data 构建 一个数据模型(第 13 章会介绍 Core Data)。本章的应用程序不会创建任何模型对象,因为我们 不需要保存数据。后面的章节会介绍模型对象,以实现更复杂的应用程序。 控制器组件通常由应用程序的具体类组成。控制器可以是完全自定义的类(NSObject 子类), 但在多数情况下控制器是 UIKit 框架提供的那些通用控制器类(比如 UIViewController,稍后就 会介绍)的子类。这么说吧,通过继承一个已有的类,可以免费获取大量的实用功能,这样就不 用再花时间重复造轮子了。 随着对 Cocoa Touch 的深入学习,很快就可以看到 UIKit 框架中的类遵循 MVC 原则的情况。 在开发时牢记这个概念,就能够创建出简洁而易于维护的代码。 3.2 创建项目 现在开始创建下一个 Xcode 项目。这个项目与上一章的项目使用相同的模板 Single View Application。从这个简单的模板入手,更容易理解视图和控制器之间的协作。后面的章节会陆续 介绍其他一些模板。 启动 Xcode,选择 File➤New➤New Project...(或者按下 shift+command+N)。选择 Single View Application 模板,然后点击 Next。 然后会看到一个与上一章相同的选项表单。在 Product Name 字段中填入 Button Fun 作为这 个新应用程序的名字。Organization Name、Company Identifier 以及 Class Prefix 这三个字段的值 默认与上一个项目相同(Apress、com.apress、BID),可以不用管它们。 36 第3 章 实现基本交互 与“ Hello, World”一样,我们要编写的是个 iPhone 应用程序,所以在 Devices 中选择 iPhone。 最终的选项表单如图 3-2 所示。 图 3-2 项目命名和项目选项 点击 Next,Xcode 会提示你选择项目的保存位置。可以把这个项目与本书其他项目保存在一 起。对于 Create git repository 选项,可以根据自己的喜好来决定是否选择。 3.3 视图控制器 与上一章一样,本章稍后会使用界面构建器为应用程序设计一个视图(或者说是用户界面)。 在此之前,先来看看那些 Xcode 自动创建的源代码文件,需要对它们进行一些修改。这一章终于 要开始编写代码了。 开始修改之前,先来看看这些已经创建好的文件。在项目导航面板中,Button Fun 分组应该 已经展开了(如果还没有展开,可以点击旁边的三角形按钮展开它),如图 3-3 所示。 Button Fun 文件夹包含 4 个源代码文件(以.h 或者.m 结尾)、一个 storyboard 文件和一个包含 了应用程序所需全部图片的 xcassets 文件。这 4 个源代码文件实现了应用程序所需的两个类:应 用程序委托(application delegate),以及用于这个应用仅有的一个视图的视图控制器。再次提醒 一下,Xcode 为所有的类都自动添加了之前指定的类名前缀(BID)。 3.3 视图控制器 37 1 2 3 4 5 11 6 7 8 9 10 图 3-3 项目导航面板中显示了项目模板自动创建的类文件。注意,类文件的名称前都 自动添加了类名前缀 本章稍后会介绍应用程序委托。先来看看 Xcode 自动创建的视图控制器类。 名为 BIDViewController 的控制器类负责管理应用程序的视图。名称中的 BID 部分就是之前 指定的类名前缀,名称中的 ViewController 部分则表明这个类是一个视图控制器。点击分组和文 件(Groups & Files)面板中的 BIDViewController.h,就可以查看这个类的头文件了: 没什么内容,是吧。BIDViewController 是 UIViewController 的子类。UIViewController 是 之前提到的通用控制器类中的一个,它是 UIKit 框架的一部分,通过继承这个类,可以获得大量 的常用功能。Xcode 并不知道我们的应用程序会有哪些功能,但它知道应用程序必须具备哪些功 能,所以它创建了这个类,可以在此基础上手动编写应用程序的具体功能。 3.3.1 输出接口和操作方法 第 2 章曾经使用 Xcode 的界面构建器创建了一个简单的用户界面。刚才也看到了视图控制器 类的框架。一定有某种方式可以让视图控制器类中的代码与分镜文件中的对象交互,对不对? 当然可以!控制器类可以通过一种名为输出接口(outlet)的特殊属性来引用分镜或 nib 文件 中的对象。可以把输出接口看做指向用户界面中对象的指针。例如,假设在界面构建器中创建了 一个文本标签(像第 2 章那样),希望可以在代码中改变该标签的文本。声明一个输出接口,并 且把它与标签对象关联起来,就可以在代码中使用这个输出接口来修改标签的显示文本了。本章 会详细介绍这个方法。 另一方面,可以对 nib 文件中的界面对象进行设置,以触发控制器类中的某些特殊方法。这 些特殊方法称为操作方法(action method),或者简称为操作(action)。例如,可以在界面构建器 中进行设置,当用户点击一个按钮时,就调用代码中的某个相关操作方法。甚至还可以在界面构 建器这样设置:当用户第一次触碰一个按钮时调用某个操作方法,当手指离开该按钮时调用另一 38 第3 章 实现基本交互 个操作方法。 Xcode 支持多种创建输出接口和操作方法的方法,一种方法是在源代码里先设定好,然后再 使用界面构建器与将它们与相应的代码关联起来。Xcode 的辅助视图提供了一种更快更直观的方 式,只需要一步就可以创建输出接口和操作方法并完成与代码的关联。稍后就会介绍这个方法。 不过,在进行关联之前,还需要再详细了解一下输出接口和操作方法。输出接口和操作方法是创 建 iOS 应用的两个最基础的模块,所以必须要理解它们的本质和原理。 1. 输出接口 输出接口是 Objective-C 类的一种特殊属性,用 IBOutlet 关键字声明。输出接口可以在控制 器类的头文件中声明,或者也可以在控制器的实现文件的类扩展(class extension)中的某个特定 部分进行声明,如下所示: 这个例子声明了一个名为 myButton 的输出接口,可以让它指向界面构建器中的任何按钮。 IBOutlet 并不属于 Objective-C 内置的关键字,仅仅是一个简单的位于系统头文件中的,用 C 写成的预处理指令,它的定义如下所示: 是不是感到很困惑?对于编译器来说,IBOutlet 什么作用都没有。它唯一的作用就是告诉 Xcode,这个属性会与 nib 文件中的对象进行关联。任何需要与 nib 文件中的对象进行关联的属性, 都必须使用 IBOutlet 关键字进行声明。幸好,Xcode 能够自动创建输出接口。 输出接口的变化 随着时间的推移,苹果公司改变了输出接口的声明方式和使用方式。鉴于有时可能会遇到 比较老的代码,所以一起来看看输出接口的变化吧。 在本书的第 1 版中,我们需要为输出接口同时声明属性和相应的实例变量。那时,属性是 Objective-C 语言中的一个新概念,必须要为属性声明相应的实例变量,请看: 在那时,我们是在实例变量的声明前使用 IBOutlet 关键字,就像这样: 当时苹果的示例代码使用的就是这种方式,这也是 IBOutlet 关键字在 Cocoa 和 NeXTSTEP 中的常规用法。 到编写本书第 2 版时,苹果把 IBOutlet 关键字从实例变量的声明移到了属性声明中,这 3.3 视图控制器 39 1 2 3 4 5 11 6 7 8 9 10 也是目前的标准做法,如下所示: 尽管这两种方法都可行(现在仍是如此),但本书遵循苹果的声明方式修改了书中的代码, 把 IBOutlet 关键字从实例变量的声明中移除,放到了属性声明中。 近年来,苹果把默认的编译器从 GCC 改为了 LLVM(Low Level Virtual Machine,底层虚 拟机)之后,就不再需要为属性声明相应的实例变量了。对于一个属性来说,如果 LLVM 找 不到与之对应的实例变量,它就会自动创建一个实例变量。因此,在本书这一版中,不再专门 为输出接口声明实例变量。 所有的这些方法实际上都在做同一件事,那就是让界面构建器知道输出接口的存在。苹 果目前推荐的方式是把 IBOutlet 关键字放在属性声明中,所以我们遵循这一方式。希望你能 了解这些历史背景,以防遇到比较老的代码(IBOutlet 关键字出现在实例变量的声明中)而 迷惑不解。 要了解 Objective-C 属性的更多信息,可以阅读由 Scott Knaster、Waqar Malik 和 Mark Dalrymple 合著的《Objective-C 基础教程(第 2 版)》,或者是苹果开发者网站上的文档 “Introduction to the Objective-C Programming Language”(网址是 http://developer.apple.com/ library/ios/#documentation/ Cocoa/Conceptual/ProgrammingWithObjectiveC)。 2. 操作方法 简单来说,操作方法是一种返回类型为 IBAction 的特殊方法,返回类型 IBAction 告诉界面 构建器这个方法可以被 nib 文件中的控件触发。操作方法的声明通常如下所示: 或者是: 操作方法的名称并没有什么特殊要求,可以使用任何你喜欢的方法名称,但是返回类型必须 是 IBAction,实际上这相当于把返回类型声明为 void。返回类型为 void 的方法不返回任何值。而 且,操作方法要么不接受任何参数,要么只接受一个参数(通常命名为 sender)。sender 参数是 一个指针,在操作方法被调用时,sender 指向触发该方法的对象。例如,如果用户按下某个按钮 时触发了这个操作方法,那么 sender 就指向这个被按下的按钮。sender 参数的存在使一个操作方 法可以对多个控件作出响应。可以通过 sender 参数来确定到底是哪个控件触发了这个操作方法。 提示 事实上,还有一种不常用的 IBAction 声明方式,如下所示: 下一章会介绍控件事件。 40 第3 章 实现基本交互 如果声明了一个带有 sender 参数的操作方法,方法内部却没有使用到这个参数,也不会有 任何问题。以后可能会看到很多这样的代码。Cocoa 和 NeXTSTEP 中的操作方法需要接受 sender 参数,不管会不会用到。所以很多 iOS 代码(尤其是早期的代码)都是用这种方式编写的。 现在,你已经了解了操作方法和输出接口的基本概念,接下来就会学习如何在设计用户界面 时使用它们。在开始之前,需要先进行一些清理工作,以保持代码整洁有序。 3.3.2 清理视图控制器 在项目导航面板中单击 BIDViewController.m,打开这个实现文件。可以看到,文件中有一些 包含 viewDidLoad 和 didReceiveMemoryWarning 等方法的样板代码,这是由创建项目时选择的项目 模板提供的。在 UIViewController 的子类中通常会用到这些方法,所以 Xcode 提供了这些基本的 代码片段,如果需要的话,我们可以直接在这些方法中添加自己的代码。但是,这个项目并不需 要这些代码片段,而它们既占用了空间又使代码不易阅读。为了简化以后的工作,应该删除那些 不需要的代码。 在这个文件的顶部,可以看到一个空的类扩展。类扩展是一种特殊的 Objective-C 分类 (category)声明,可以在其中声明方法和属性,但是这些方法和属性只能在当前文件的 implementation 块中使用。本书后面会用到类扩展,但是现在并不需要,所以应该把这个空的 @interface... @end 块删除。完成之后,实现文件看起来应该是这个样子: 现在就简洁多了,是不是?不用担心刚才删除的那些方法,本书后面会介绍这些方法中的大 部分内容。 3.3.3 设计用户界面 记得保存刚才所做的修改,然后单击 Main.storyboard 文件,就可以在 Xcode 的界面构建器中打 开应用程序的视图(参见图 3-4)。你可能还记得上一章提到,编辑器的白色窗口中展示了应用程 序的唯一一个视图。现在需要在这个视图中添加两个按钮和一个标签,从而实现图 3-1 所示的效果。 先来思考一下这个应用程序。需要在用户界面中添加两个按钮和一个标签,这个过程与上一 章类似。不过,还需要通过输出接口和操作方法才能使应用程序与用户交互。 每个按钮都需要在控制器上触发一个操作方法。可以选择让每个按钮调用不同的操作方法, 但由于它们本质上做的是同一件事(更改标签的文本),所以调用同一个操作方法。我们使用 sender 参数(之前的“操作方法”一节讨论过)来区分这两个按钮。除了操作方法,还需要一个 与标签关联的输出接口,修改标签的显示文本。 首先添加按钮,然后再添加标签。设计用户界面时创建对应的操作方法和输出接口。也可以 手动声明操作方法和输出接口,然后将用户界面元素与它们关联起来,不过,既然 Xcode 会自动 3.3 视图控制器 41 1 2 3 4 5 11 6 7 8 9 10 完成这些工作,为什么要手动去做呢? 图 3-4 打开Main.storyboard 文件就可以对 Xcode 的界面构建器进行编辑了 1. 添加按钮和操作方法 第一步要向用户界面添加两个按钮。随后让 Xcode 创建一个空的操作方法,我们可以把两个按 钮都关联到这个操作方法。这样,用户点击按钮时就会调用这个操作方法,其中的代码就会执行。 选择 View➤Utilities➤Show Object Library(或按下 control+option+command+3)打开对象库。 在对象库的搜索框中输入 UIButton(实际上只需要输入开头的 4 个字母 UIBu 来筛选列表,就可 以在对象列表的顶部看到 UIButton 了),如图 3-5 所示。 图 3-5 对象库中显示的按钮 42 第3 章 实现基本交互 把 Button 从库中拖到编辑区中白色的窗口中,这样就会在应用程序视图中添加一个按钮。 将该按钮放置在视图左侧,参照蓝色的引导线将按钮放在距离左侧边缘合适的位置。在垂直方向 上,参照蓝色的引导线将按钮放在视图的下半部分。可以参考图 3-1 的布局来放置按钮。 注意 在界面构建器中移动对象时出现的蓝色细引导线可以帮助你遵循 iOS Human Interface Guidelines(通常简称为 HIG)。苹果的 HIG 可以帮助用户更好地设计 iPhone 和 iPad 应用 程序。HIG 会告诉你应该如何设计用户界面,也会告诉你哪些设计不应该出现。建议阅 读一下这份文档,它包含了很多有用的信息,这是每个 iOS 开发者都应该了解的。可以在 以下地址找到这个文档:http://developer.apple.com/ios/library/documentation/UserExperience/ Conceptual/ MobileHIG/。 双击新添加的按钮,可以编辑按钮标题,将其标题设为 Left。 现在该 Xcode 发挥作用了。选择 View➤Assistant Editor➤Show Assistant Editor(或者按下 option+command+return)打开辅助编辑器。注意项目窗口右上方的 7 个按钮,可以点击最左边一 组按钮中间的按钮,显示或者隐藏辅助编辑器(参见图 3-6)。 图 3-6 Show the Assistant editor 开关按钮 辅助编辑器会出现在编辑面板的右侧,除非你特别指定辅助编辑器的位置(参见辅助编辑器 菜单的选项)。辅助编辑器将出现在编辑面板的右侧,辅助编辑器左侧显示的内容仍然是界面构 建器,而右侧显示的是 BIDViewController.h 或 BIDViewController.m(也就是当前查看的视图所 属的视图控制器类的头文件以及实现文件)。 提示 打开辅助编辑器之后,或许需要调整窗口大小以获得足够的工作空间。如果你的显示器 屏幕比较小(比如 MacBook Air 上的显示器),那么可以关闭 utility 视图或项目导航面板, 从而获得足够的空间,有效地使用辅助编辑器。可以通过项目导航窗口右上角的 3 个视 图按钮方便地完成这个操作(参见图 3-6)。 还记得上一章提到过的 View Controller 图标吗?很多地方都与它有关。Xcode 知道我们的视 图控制器类负责显示这个视图,因此辅助编辑器会向我们显示视图控制器类的头文件或实现文 件,我们只可能在这里创建并连接操作方法和输出接口。 前面提到,BIDViewController 类中并没多少内容。它只是一个空的 UIViewController 子类, 但它很快就不再是空的子类了! 3.3 视图控制器 43 1 2 3 4 5 11 6 7 8 9 10 现在要让 Xcode 自动创建一个新的操作方法,并把它与之前创建的按钮关联起来。这些定义 代码要加在头文件中。如果辅助编辑器当前显示的不是头文件,请在上面的跳转栏中选择 BIDViewController.h 文件。 首先,点击新添加的按钮以选中它。然后,按住键盘上的 control 键不放开,接着用鼠标把 按钮拖向辅助编辑器的源代码中。这个过程中会看到一条蓝色的直线,从按钮一直连到光标(参 见图 3-7)。我们就是通过这条蓝色的直线把界面构建器中的对象连接到代码或其他对象上。 图 3-7 按住 control 键并用鼠标拖动到源代码上,可以看到创建输出接口、操作方法或 者输出接口集合的选项 提示 可以将这条蓝色直线拖动到任何地方与按钮建立关联:可以拖动到辅助编辑器中的头文 件、File’s Owner 图标、编辑面板左侧的任何其他图标,甚至是编辑区域中的其他对象。 如果把指针移动到@interface 和@end 关键字之间(参见图 3-7),就会弹出一个灰色的提示 框,告诉你如果在这里放开鼠标的话可以插入输出接口、操作方法,或输出接口集合。 注意 本书会使用操作方法和输出接口,但是不会用到输出接口集合。使用输出接口集合可以 把多个同类型的对象关联到一个 NSArray 属性,而不必为每个对象单独创建一个属性。 44 第3 章 实现基本交互 请放开鼠标来完成关联,此时会出现一个浮动的弹出框,如图 3-8 所示。可以在这个窗口中 定制新操作方法。在这个窗口中,点击名为 Connection 的弹出菜单,把当前的选择 Outlet 改为 Action。这就告诉 Xcode,我们要创建的是一个操作方法,而不是输出接口。 图 3-8 按住Control 键并用鼠标拖动到源代码之后出现的浮动弹出框 现在这个浮动弹出框变成了图 3-9 所示的样子。在 Name 字段中输入 buttonPressed。输入完 成后不要按 return 键。按下 return 键将会结束操作方法的设置,但是我们还没有完成这个操作方 法的定制。请按 Tab 键,并在 Type 字段中输入 UIButton,替换默认的 id 值。 图 3-9 将关联类型改成 Action 后,弹出框的外观发生了改变 注意 也许你还记得,id 是一种泛型指针,它能指向任何 Objective-C 类。在这里保持 Type 字段 中的值为 id 不变,这样也能正常工作,但是,如果把它更改为期望调用该方法的类,当 试图通过一个错误类型的对象调用该方法时编译器就能发出警告。有时你希望利用这种 灵活性,以便通过不同类型的控件调用同一个操作方法,这种情况下保留默认设置 id 即 可。在本例中,我们只会通过按钮对象调用这个方法,所以应该将其改为 UIButton,让 Xcode 和 LLVM 知道我们的意图。现在,如果不小心把其他对象关联到这个方法,就会 得到警告信息。 3.3 视图控制器 45 1 2 3 4 5 11 6 7 8 9 10 在 Type 下面还有两个字段,保留它们的默认值即可。在 Event 字段中指定什么时候调用这 个方法。默认值 Touch Up Inside 仅会在用户的手指离开屏幕(且用户的手指在离开屏幕之前依然 位于按钮内部)时触发相应的操作方法。这是按钮使用的标准事件。这就给了用户一个重新考虑 的机会。如果用户的手指在离开屏幕之前从按钮上移到了别处,那么就不会触发这个方法。 在 Arguments 字段中选择操作方法要用到的方法签名(三选一)。本例中需要使用 sender 参 数来区分触发方法的按钮。默认值就是 sender,所以不需要更改。 按下 return 键,或者点击弹出框中的 Connect 按钮,Xcode 就会自动插入操作方法。现在 BIDViewController.h 文件应如下所示: Xcode 在类的头文件中添加了一个方法声明。使用辅助编辑器顶端的跳转栏切换到 BIDViewController.m 文件中,可以看到 Xcode 已经自动添加了一个方法存根。 很快我们会再次讨论这个方法存根,编写一些代码用于响应按钮的点击事件。除了创建方法 声明和方法实现,Xcode 还对按钮和这个操作方法进行了关联,并且把这些信息存储在分镜文件 中。这意味着,不需要再做任何额外的工作,就可以保证按钮在应用程序运行时调用这个操作方 法。 再来看 Main.storyboard 文件,再从对象库中拖出一个按钮,这次把新的按钮放在屏幕右边。 然后双击按钮,把它的标题改为 Right。这时会出现蓝色的引导线,帮助你把按钮放到距离右侧 边缘恰当的位置上,也可以帮你把新按钮与另一个按钮在垂直方向上对齐。 提示 除了从库中拖出一个新对象,还可以按住 option 键不放并且拖曳原始对象(本例中为 Left 按钮)。按住 option 键就是告诉界面构建器创建一个被拖曳对象的副本。 这次不必为新按钮创建新的操作方法。可以直接把这个新按钮关联到之前 Xcode 为我们创建 的操作方法。应该怎么做呢?关联的过程与之前为第一个按钮创建操作方法的过程非常相似。 修改完按钮名称之后,按住键不放开,把按钮拖向辅助编辑器。无所谓是当前是.h 文件还是.m 文件,只需要把鼠标拖向 buttonPressed:方法的位置,当指针接近 buttonPressed:方法声明时, 这个方法会高亮显示,同时会弹出一个显示 Connect Action 的灰色提示框(参见图 3-10)。看到 这个弹出提示框之后,松开鼠标,Xcode 就会把按钮与这个已有的操作方法关联起来。现在,与 另一个按钮一样,点击这个新添加的按钮就会触发 buttonPressed:方法。 再说一遍,如果用这种方式把按钮拖曳到实现文件(.m 文件)中的操作方法,效果也是一样 的。也就是说,按住 control 键拖曳按钮时,既可以拖向 BIDViewController.h 文件中的 buttonPressed 46 第3 章 实现基本交互 方法声明上,也可以拖向 BIDViewController.m 文件中的 buttonPressed 方法实现上。Xcode 真是太 智能了! 图 3-10 把按钮拖曳到一个已有的操作方法上,就可以将按钮与该操作方法关联起来 2. 添加标签和输出接口 在对象库的搜索框里输入 Label,可以找到用户界面元素 Label(参见图 3-11)。把 Label 拖 曳到用户界面中,放置在两个按钮的上方。然后,调整标签的大小,从屏幕左侧边缘拉伸到右侧 边缘。这样标签就有足够的空间来容纳需要显示给用户的文本。 图 3-11 对象库中的标签 标签中的文本默认是左对齐的,但是我们希望它居中对齐。选择 View➤Utilities➤Show Attributes Inspector(或者按下 option+command+4)打开属性检查器(参见图 3-12)。确保选中了 这个标签,然后在属性检查器中找到 Alignment 按钮集合。选择中间的按钮就可以使标签中的文 本居中显示。 用户点击按钮之前,我们不希望标签显示任何文本,所以双击标签(这样就选中了标签的文 本),按下键盘上的 delete 键。这会删除标签当前显示的文本。按下 return 键提交更改。这样一 来,标签在未选中时就看不到了,不过不用担心,它仍然在那里。 3.3 视图控制器 47 1 2 3 4 5 11 6 7 8 9 10 提示 如果有不可见的用户界面元素,比如空白标签,而你又希望能看到它们所在的位置,可 以从 Editor 菜单中选择 Canvas,然后从弹出的子菜单中勾选 Show Bounds Rectangles。 图 3-12 标签的属性检查器 最后剩下的工作就是为标签创建输出接口。这与之前创建并且关联操作方法的方式完全相 同。确保打开了辅助编辑器,并且显示着 BIDViewController.h 文件。如果需要切换当前显示的文 件,可以使用辅助编辑器上方跳转栏中的弹出菜单。 接着,选中界面构建器中的标签控件,按住 control 键把它从标签拖向头文件。当光标位于 已有的操作方法的上方,看到如图 3-13 所示的画面时,松开鼠标和键盘,你将再次看到图 3-8 所示的弹出窗口。 我们要创建一个输出接口,所以保留 Connection 中的默认值 Outlet。并且要为这个输出接口 指定一个描述性的名称,以便在编写代码时能够知道这个输出接口的作用。在 Name 字段中输入 statusLabel。Type 字段使用默认值 UILabel。对于最后一个名为 Storage 的字段,保留默认值即可。 按下 return 键提交更改,Xcode 将会在代码中插入一个输出接口属性。现在控制器类的头文 件应该是下面这个样子: 48 第3 章 实现基本交互 图 3-13 按住control 键并拖动控件,创建一个输出接口 现在,有了一个输出接口,而且 Xcode 也已经自动把标签与这个输出接口关联了起来。这意 味着,如果在代码中对 statusLabel 进行更改,就会影响到用户界面中的标签。例如,如果设置 statusLabel 的 text 属性,就会改变显示给用户的文本。 自动引用计数 如果你已经很熟悉 Objective-C,或者读过本书的前几版,就会发现,这里没有 dealloc 方法。我们没有释放实例变量! 警报!警报!这很危险! 事实上,你大可以放松。这里没有问题。一点儿也不危险,真的。 已经不必再释放对象了。其实这么说并不完全正确。需要释放对象,但是苹果公司在 Xcode 中使用的 LLVM 编译器相当智能,可以自动释放对象。它通过 ARC 功能来完成这个繁重工作。 这就意味着不再频繁地调用 dealloc 方法了,也不需要再关心 release 或者 autorelease 的调 用了。ARC 的出现是一个巨大的进步,本书所有的例子都使用 ARC。过去两年内 ARC 在 Xcode 中是可选的内容,不过到了现在你创建的每个项目都会默认启用它。 ARC 只适用于 Objective-C 对象,并不能用于 Core Foundation 对象或是使用 malloc()分 配的内存以及类似的东西,也会有一些陷阱和注意事项,但是大多数情况下,已经没有必要 担心内存管理了。 要了解更多关于 ARC 的信息,可以在以下网址查看 ARC 的发布说明: 3.3 视图控制器 49 1 2 3 4 5 11 6 7 8 9 10 ARC 确实很酷,但它并不是万能的。仍然需要理解 Objective-C 内存管理的基本规则,才 能避免使用 ARC 时遇到麻烦。要想重温 Objective-C 内存管理机制,可以阅读苹果公司的 Memory Management Programming Guide,地址是:http://developer.apple.com/library/ios/ #documentation/Cocoa/Conceptual/MemoryMgmt/。 3. 编写操作方法 至此,已经完成了用户界面的设计,并且将用户界面与输出接口和操作方法都进行了关联。 最后要做的就是,点击按钮时,使用这些操作方法和输出接口来设置标签的显示文本。在项目导 航面板中单击 BIDViewController.m 文件,并在编辑器中打开它。找到之前 Xcode 为我们创建的 空的 buttonPressed:方法。 为了区分这两个按钮,需要用到 sender 参数。使用 sender 参数可以获取到被点击的按钮标 题,根据这个标题创建一个新的字符串,然后把这个字符串作为标签的文本。在这个空的方法中 添加以下加粗代码: 这段代码非常直观。第一行使用 sender 参数获取被点击的按钮的标题。由于按钮在不同状 态下可以有不同的标题,因此使用 UIControlStateNormal 参数表明我们需要获取的是按钮在正常 状态时(未被按下时)的标题。获取控件(按钮是控件的一种)标题时,通常都是使用这种状态。 第 4 章会详细介绍控件状态。 接下去的一行代码创建了一个新的字符串,新字符串的内容是在按钮标题(上一行代码获取 到的标题)末尾添加“button pressed.”文本拼接而成的。因此,如果点击标题为 Left 的按钮, 就会创建一个内容为“Left button pressed.”的字符串。最后一行代码就是把这个新的字符串赋给 标签的 text 属性,这样就可以改变标签的显示文本。 消息嵌套 一些开发者经常会嵌套使用 Objective-C 消息。在学习过程中你可能会看到类似这样的代码: 这一行代码的功能与之前 buttonPressed:方法中的前两行代码完全等价。这是因为 Objective-C方法可以嵌套,这样就不必为每一个嵌套的方法调用都创建一个对象来保存返回值。 为使代码清晰,本书的示例代码中通常不会嵌套 Objective-C 消息,除非是对 alloc 和 init 的调用,因为它们的嵌套调用已经是长期以来的一种标准约定。 50 第3 章 实现基本交互 3.3.4 运行应用 到现在为止,这个项目基本上就完成了。准备好运行这个应用了吗?我们来试试! 选择 Product➤Run,如果碰到了编译或链接错误,请参照本章前面部分对比一下你的代码。 代码正确构建之后,Xcode 将会启动 iOS 模拟器运行这个应用程序。点击右边的按钮,标签应该 会显示“Right button pressed.”(参见图 3-1)。如果再点击左边的按钮,标签文本将会变为“Left button pressed.”。 目前为止一切顺利,但是,如果回头看一下图 3-1,会发现有一件事情忘记做了。最终结果屏 幕截图中的按钮名称是用粗体显示的,但是目前只显示了纯文本。可以使用 NSAttributedString 加粗文本。 3.3.5 样式文本 NSAttributedString 可以对字符串附加格式信息,比如字体和段落对齐。可以在整个字符串 上使用这些元数据,也可以对字符串的不同部分使用不同的属性。如果你想在文字处理程序中对 不同文本片段使用不同的格式,那么 NSAttributedString 正是你想要的! 然而,苹果的 UIKit 中一直都没有一个类能够处理属性字符串(attributed string)。如果希望 展现一个同时包含加粗文本和正常文本的标签,要么使用两个标签,要么直接在自己的视图上绘 制文本。这些方法并不是无法实现,但是使用起来非常复杂,让大多数开发者都望而却步。在 iOS 6 中对于样式文本有了很大的改善,大部分主要的 UIKit 控件都允许使用属性字符串了。对 这个例子里的 UILabel 来说,只需要创建一个属性字符串,然后把它赋给标签的 attributedText 属性就可以了。 那么,修改 buttonPressed:方法,删除划掉的代码行,添加加粗显示的代码行,如下所示: 新代码做的第一件事情就是基于我们要显示的文本创建一个属性字符串(NSMutable- AttributedString 的一个实例)。这里需要使用可变的属性字符串,因为需要改变它的属性。 3.4 应用程序委托 51 1 2 3 4 5 11 6 7 8 9 10 接下来,创建一个用于保存字符串属性的字典。现在只需要一种属性,所以这个字典只包 含一个键值对。通过名为 NSFontAttributeName 的键可以为属性字符串的一部分指定字体。这里 传入的值是一种名为“bold system font”的字体,字体大小与标签当前使用的字体大小一致。 相对于使用硬编码的字体名称,通过这种方式指定字体更加灵活,因为系统总是能够恰当地展 现加粗字体。 提示 如果刚接触 Objective-C 不久,你可能还不熟悉新的字典创建语法,但是这种语法非常简 单。Xcode 内置的 LLVM 提供了非常简洁的字典创建语法,与显式地在 NSDictionary 上 调用方法相比,新语法更简单易用。它的基本形式如下所示: 使用这种方式创建字典时,除了不再需要输入冗长的类名和方法名之外,它还能自动以 “正确的顺序”来排列这些键值对,与很多脚本语言类似,比如 Ruby、Python、Perl、 JavaScript。 除了新的字典语法,2012 年的时候也添加了新的数组语法和数值语法。本书的代码示例 使用这些新的语法片段。 然后,取得 plainText 字符串中待改变的子字符串(也就是这里的 title)所属的范围(由 一个起始索引和一个长度组成)。把属性应用到属性字符串,然后把属性字符串赋给标签。 现在,点击 Run 按钮运行应用,可以看到标签中的按钮名称是以粗体显示的。 3.4 应用程序委托 很好,应用程序运行起来了!在进入下一个主题之前,我们花点时间来看看两个还没有介绍 过的源代码文件:BIDAppDelegate.h 和 BIDAppDelegate.m。这两个文件实现了应用程序委托 (application delegate)。 Cocoa Touch 广泛地使用了委托(delegate),委托是负责为其他对象处理特定任务的对象。 通过应用程序委托,能够在某些预定义时间点为 UIApplication 类做一些工作。每个 iOS 应用程 序都有且仅有一个 UIApplication 实例,它负责应用程序的运行循环,以及处理应用程序级的功 能(比如把输入信息分发给恰当的控制器类)。UIApplication 是 UIKit 的标准组成部分,它主要 在后台处理任务,所以一般来说不用管它。 在应用程序执行过程中的某些特定时间点,UIApplication 将会调用特定的委托方法(如果 委托对象存在,并且实现了相应的委托方法)。例如,如果需要在程序退出时触发一段代码,可 以在应用程序委托中实现 applicationWillTerminate:方法,在这个方法内编写想要的代码即可。 52 第3 章 实现基本交互 通过这种委托,开发者可以实现通用的应用程序级行为,而不需要继承 UIApplication 类,也不 需要了解它的任何内部机制。 在项目导航面板中单击 BIDAppDelegate.h,查看应用程序委托的头文件,它应该如下所示: 其中有一行代码需要特别注意: 注意到尖括号里面的值了吗?它表示这个类遵循 UIApplicationDelegate 协议。按住 option 键,光标应该变成了十字形。把光标移到 UIApplicationDelegate 这个单词上,现在光标应该变 成了问号,并且 UIApplicationDelegate 被高亮显示了,类似于浏览器中的链接(参见图 3-14)。 图 3-14 在Xcode 中按住 Option 键,把光标指向代码中的某个符号,该符号就会高亮 显示,同时光标会变成问号 仍然按住 option 键不放开,单击这个链接。这时候会弹出一个小窗口,其中显示了 UIApplica- tionDelegate 协议的简单概述,如图 3-15 所示。 图 3-15 按住option 并单击源代码中的,Xcode 就会弹出这 个被称为 Quick Help 的面板,其中简单描述了协议的相关内容 注意这个新弹出的文档窗口(参见图 3-15)底部的两个链接。单击 Reference 链接可以查看 3.4 应用程序委托 53 1 2 3 4 5 11 6 7 8 9 10 这个符号的完整文档,单击 Declared In 链接可以查看这个符号在头文件中的定义。这个技巧也适 用于类、协议、分类名称,以及编辑器面板中显示的方法名称。只要按住 option 键并单击某个单 词,Xcode 就会在文档浏览器中搜索这个词。 了解如何快速查找文档中的内容绝对大有裨益,但是查看这个协议的定义可能更为重要。开 发者可以通过这个协议的定义来了解这个应用程序委托能够实现哪些方法,以及这些方法分别会 在什么时候调用。有必要花些时间来阅读这些方法的说明。 注意 如果你之前使用过 Objective-C,但是没有用过 Objective-C 2.0,那么你需要知道的是, 现在可以为协议指定可选方法了。UIApplicationDelegate 包含很多可选方法。不过,不 需要在应用程序委托中实现任何可选方法,除非真的有必要。 回到项目导航面板,单击 BIDAppDelegate.m 来查看应用程序委托的实现。它应该如下所示: // 在程序启动之后,重写自定义设置的位置 // 应用即将从活动状态切换到不活动状态时会触发这个方法。在出现某种临时中断(比如有 来电或者短信)或用户退出应用程序时都会触发这个方法,然后应用就会转换为后台运行 // 可以在这个方法中暂停正在进行的任务,禁用定时器,降低 OpenGLES 帧率。如果是游戏应 用,应该在这个方法中暂停游戏 // 在该方法中释放共享资源,保存用户数据,清除定时器,并存储足够的应用状态信息,目 的是当应用终止时,将它恢复到当前状态 // 如果你的应用支持在后台执行,那么当用户退出时调用这个方法而不是 applicationWill Terminate: 方法 // 这个方法会在应用程序从后台运行状态转换到活动状态的过程中被调用,可以在这里恢复 应用正常运行所需的信息 54 第3 章 实现基本交互 在这个文件的顶部,可以看到应用程序委托实现了文档中列出的一个协议方法,即 application:didFinishLaunchingWithOptions:。也许你已经猜到了,当应用程序完成所有的初始 化工作,并且准备好与用户进行交互时,就会调用这个方法。这个方法经常用来创建要在应用程 序运行的整个生命周期内活动的对象。 本书后面你将看到更多相关的内容。我们只是希望在本章结束之前你能够了解一些应用程序 委托的背景知识,以及所有这些内容之间的联系。 3.5 小结 本章通过一个简单的应用程序介绍了 MVC,并学习了如何创建并连接输出接口和操作方法, 实现视图控制器,以及使用应用程序委托。还学习了如何在点击按钮时触发操作方法,以及如何 在运行时更改标签的文本。虽然这只是一个简单的应用程序,但是其中用到的基本概念与 iOS 中 的所有控件都是一致的,不仅仅是按钮控件。事实上,本章对按钮和标签的使用方式适用于 iOS 中的大部分标准控件。 理解本章的所有知识点及其原理非常重要。对于没有完全理解的部分,请回头重新阅读。本 章的内容非常重要!如果尚未完全理解这些内容,本书后面创建比较复杂的界面时,你就会感到 更加困惑。 下一章将介绍其他一些标准 iOS 控件。你还可以学到如何使用警告来把重要的事项通知给用 户,以及如何通过操作表单指示用户需要在程序继续运行之前作出一个选择。做好准备之后,深 吸一口气,给自己一点鼓励,开始学习下一章的内容吧! // 当应用程序处于非活动状态时重新启动暂停(或尚未启动)的任务。如果程序之前在后台 运行,那么可以选择刷新用户界面 // 程序即将终止时调用该方法。如果有必要,那么保存数据,参见 applicationDid EnterBackground:
还剩65页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享pdf获得金币 ] 2 人已下载

下载pdf

pdf贡献者

f8g7

贡献于2014-12-15

下载需要 5 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf