内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17...

26

Transcript of 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17...

Page 1: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web
Page 2: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

内 容 提 要

本书是 iOS 开发权威指南,分 5 部分讲解如何从零起步编写并上线 iOS 应用。第一部分介绍 iOS 开发基础知识,

包括界面构建技术、基本控件、协议、表视图、屏幕适配、导航、分屏多任务等。第二部分介绍设计与架构的相关

知识,包括设计模式、分层模式、本地数据持久化等。第三部分为进阶篇,包括设置与配置、本地化、Contacts 与

ContactsUI 框架、数据交换格式、Web Service、定位服务、苹果地图等内容。第四部分介绍测试、调试和优化等相关

知识。第五部分为实战篇,涵盖代码版本管理、项目依赖管理、App Store 发布流程,以及两个真实 iOS 应用的分析设计、

编程、测试与发布过程。本书同时提供 Swift 和 Objective-C 这两种语言的代码。

本书适合所有 iOS 开发人员学习参考。

定价:119.00元

读者服务热线:(010)51095186转600 印装质量热线:(010)81055316

反盗版热线:(010)81055315

广告经营许可证:京东工商广字第 8052 号

著    关东升

责任编辑 王军花

责任印制 彭志环

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 [email protected]

网址 http://www.ptpress.com.cn

北京      印刷

开本:880×1230 1/16印张:51 字数:1646千字 2016年 6 月第 4 版印数:56 000 — 61 000册 2016年 6 月北京第 1 次印刷

Page 3: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

前 言 1

前 言

北京时间 2015 年 9 月 16 日凌晨,苹果公司正式推出了 iOS 9 系统。此次,Swift 2.0 也正式推出,Swift 经

过一年的发展已经非常健壮了,很多项目也转而使用 Swift 语言开发,但是很多老项目还使用 Objective-C 语言开

发。在这个大背景下,我们原来编写的《iOS 开发指南:从零基础到 App Store 上架》得到了广大读者的认可,

并且很多读者希望我们将其升级为 iOS 9 版本。几个月过去了,我们终于在 2016 年春节之前将书稿提交给出版社。

内容和组织结构 本书是我们团队编写的 iOS 系列丛书中的一本,目的是使有 Swift 或 Objective-C 基础的程序员通过学习本书,

从零基础学习如何在 App Store 上发布一款应用。全书共 5 部分。

第一部分为基础篇,共 9 章,介绍了 iOS 的一些基础知识。

第 1 章介绍了 iOS 的开发背景以及本书约定。

第 2 章使用故事板技术创建了 HelloWorld,同时讨论了 iOS 工程模板、应用的运行机制和生命周期、视图的

生命周期等,最后介绍了如何使用 API 帮助文档和官方案例。

第 3 章重点介绍了 Cocoa Touch 框架中构建界面的相关类,重点介绍了构建界面的 3 种技术:故事板、XIB 和纯

代码。

第 4 章重点介绍了标签、按钮、文本框、文本视图、开关、滑块、分段控件、网页控件、活动指示器、进度

条、警告框、操作表、工具栏、导航栏等基本控件。而且,每个示例都采用故事板和纯代码这两种方式实现。

第 5 章介绍了数据源协议和委托协议,然后介绍了高级视图:选择器和集合视图。

第 6 章探讨了表视图的组成、表视图类的构成和表视图的分类,使我们对表视图有了一个整体上的认识。接

下来,该章介绍了如何实现简单表视图和分节表视图,以及表视图中索引、搜索栏和分组的使用,然后学习了如

何对表视图单元格进行删除、插入、移动等操作,最后介绍了表视图 UI 设计模式方面的内容。

第 7 章介绍了 iOS 多分辨率屏幕适配方法,其中涉及的技术主要是 Auto Layout 和 Size Class。此外,该章还

介绍了 iOS 9 堆视图 StackView、iOS 屏幕的多样性、iOS 屏幕布局相关的内容。

第 8 章讨论了如何判断应用是否需要一个导航功能,并且知道在什么情况下选择平铺导航、标签导航、树形

结构导航,或者同时综合使用这 3 种导航模式。

第 9 章首先介绍 iPhone 和 iPad 设备使用场景上的差异,然后介绍了 iPad 树形结构导航、iPad 模态视图和

Popover 视图,最后介绍了 iOS 9 分屏多任务。

第二部分为设计与架构篇,共 3 章,介绍了 iOS 设计与架构的相关知识。

第 10 章讨论了 iOS 开发中 4 种常用的设计模式,分别为单例模式、委托模式、观察者模式和 MVC 模式。

在介绍每种设计模式时,我们按照问题提出、实现原理、应用案例的结构介绍了其适用情况、实现原理及用法。

第 11 章我们介绍了 iOS 平台的分层架构设计技术,归纳了 16 种分层模式,并且重点实现了 9 种模式,这些

架构设计模式将贯穿全书(包括项目实战篇中的项目),希望读者能够重点学习。

第 12 章讨论了 iOS 本地数据持久化的问题。首先,该章分析了数据存取的几种方式以及每种数据存取方式

适合什么样的场景,然后分别举例介绍了每种存取方式的实现。

Page 4: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

2 前 言

第三部分为进阶篇,共 7 章,介绍了 iOS 的一些高级知识。

第 13 章介绍了设置和配置的概念,然后通过对二者差异的探讨,介绍了什么样的项目适合放在设置里,什

么样的项目适合放在配置里。

第 14 章介绍了本地化的概念、内容和目录结构,并详细阐述了文本信息、XIB 及故事板、资源文件的本地

化。从技术角度看,应用程序的本地化比较简单,但是工作量大而且比较烦琐。

第 15 章介绍了 iOS 9 中新的访问通讯录框架——Contacts 框架,然后介绍了如何使用该框架访问联系人信息、

写入联系人信息等。最后,该章还介绍了如何使用 ContactsUI 框架提供系统界面,实现选择联系人、显示和修改联

系人以及创建联系人的操作。

第 16 章重点介绍了数据交换格式,其中主要是介绍 XML 和 JSON。

第 17 章介绍了 Web Service,并重点讨论了 REST 风格 Web Service,其中具体访问 Web Service 的 API 包括:

NSURLSession、AFNetworking 框架和 Alamofire 框架。

第 18 章讨论了 iOS 中的定位服务技术,包括地理信息编码和反编码查询。此外,该章还介绍了苹果的微定

位技术 iBeacon。

第 19 章讨论了 iOS 苹果地图的使用,包括显示地图、添加标注以及跟踪用户位置变化等。最后,我们介绍

了程序外地图的使用。

第四部分为测试、调试和优化篇,共 4 章,介绍了 iOS 高级内容,包括测试、调试和优化等相关知识。

第 20 章首先介绍了 iOS 中都有哪些调试工具并重点介绍了几个常用的工具,具体包括日志与断言的输出、

异常栈报告分析,接着讲解了如何在设备上调试应用,最后分析了 Xcode 设备管理工具的使用。

第 21 章讨论了测试驱动的 iOS 开发、测试驱动开发流程、单元测试框架 XCTest,以及如何基于分层架构进

行单元测试。

第 22 章首先介绍了 iOS 9 中提供的 UI 测试框架,最后介绍了如何基于分层架构进行 UI 测试。

第 23 章介绍了 iOS 中的性能优化方法,其中包括内存优化、资源文件优化、延迟加载、持久化优化、使用

可重用对象、并发处理与多核 CPU 等。

第五部分为实战篇,共 5 章,首先介绍了 iOS 项目开发过程中的相关技术,包括代码版本管理、项目依赖管

理以及 App Store 发布流程,最后从无到有地介绍了两个真实的 iOS 应用:MyNotes 应用和 2016 里约热内卢奥运

会应用。

第 24 章介绍了如何使用 Git 进行代码版本控制,其中包括 Git 服务器的搭建、Git 常用命令和协同开发。此

外,该章还介绍了在 Xcode 中如何配置和使用 Git 工具。

第 25 章讨论了 iOS 和 OS X 项目依赖管理工具,其中包括 CocoaPods 和 Carthage。

第 26 章通过重构 MyNotes 应用,把 MyNotes 应用的数据由原来的本地存储变成云存储。在这个过程中,我

们介绍了移动网络通信应用中分层架构设计的必要性和重要性。该章还重点介绍了基于委托模式和观察者模式通

知机制实现的分层架构设计。

第 27 章探讨了如何在 App Store 上发布应用,介绍了应用的发布流程以及应用审核不通过的一些常见原因。

第 28 章介绍了完整的 iOS 应用分析设计、编程、测试和发布过程,其中采用了敏捷开发方法。此外,该项

目采用分层架构设计,这对于学习 iOS 架构是非常重要的。

书中并没有包括多媒体等知识,我们会在另外一本 iOS 开发书中介绍,具体进展请读者关注智捷 iOS 课堂官

方网站:http://www.51work6.com。

本书服务网址 为了更好地为广大读者提供服务,我们专门为本书建立了一个服务网址 www.51work6.com/book/ios14.php,

大家可以查看相关出版进度,并对书中内容发表评论,提出宝贵意见。

Page 5: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

前 言 3

源代码 书中包括了 100 多个完整的案例项目源代码,大家可以到本书网站 www.51work6.com/book/ios14.php 下载或

者到图灵社区(iTuring.cn)本书主页免费注册下载。

免费相关视频 为了使广大读者能够快速学习本书,智捷课堂给广大读者提供了此书相关的免费视频,具体包括:从零开始

学 Swift、从零开始学 Objective-C 以及部分 iOS 相关视频。读者凭书中夹带的书签下方的优惠码,就可以购买价

值 50 元内视频课程。具体使用说明:首先在智捷课堂视频平台(www.zhijieketang.com)上注册并登录,然后找

到相应课程,接着选择页面中的“购买课程”→“去支付”→“输入优惠码”→“使用”即可。

勘误与支持

我们在网站 www.51work6.com/book/ios14.php 中建立了一个勘误专区,希望及时地把书中的问题、失误和纠

正反馈给广大读者。如果你发现了任何问题,均可以在网上留言,也可以发送电子邮件到 [email protected],我

们会在第一时间回复你。此外,你也可以通过新浪微博与我联系,我的微博为:@tony_关东升 。

致谢

在此感谢图灵的王军花责编给我们提供的宝贵意见,感谢智捷 iOS 课堂团队的赵志荣参与内容讨论和审核,

感谢赵大羽老师手绘了书中全部草图,并从专业的角度修改书中图片,力求更加真实完美地奉献给广大读者。此

外,还要感谢我的家人容忍我的忙碌,以及对我的关心和照顾,使我能抽出这么多时间,投入全部精力专心编写

此书。

由于时间仓促,书中难免存在不妥之处,请读者原谅。

关东升

2016 年 2 月于北京

Page 6: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

目 录 1

目 录

第一部分 基 础 篇

第 1 章 开篇综述 ...................................................... 2 1.1 iOS 概述 .................................................................. 2

1.1.1 iOS 介绍 ...................................................... 2 1.1.2 iOS 9 新特性 ................................................ 2

1.2 开发环境及开发工具 .............................................. 3 1.3 本书约定 ................................................................. 4

1.3.1 案例代码约定 .............................................. 4 1.3.2 图示的约定 .................................................. 5 1.3.3 方法命名约定 .............................................. 6 1.3.4 构造函数命名约定 ...................................... 7 1.3.5 错误处理约定 .............................................. 8

第 2 章 第一个 iOS 应用程序 ............................... 10 2.1 创建 HelloWorld 工程 ........................................... 10

2.1.1 创建工程 ................................................... 10 2.1.2 Xcode 中的 iOS 工程模板 ......................... 14 2.1.3 应用剖析 ................................................... 15

2.2 应用生命周期 ....................................................... 17 2.2.1 非运行状态——应用启动场景 ................ 19 2.2.2 点击 Home 键——应用退出场景 ............ 20 2.2.3 挂起重新运行场景 .................................... 22 2.2.4 内存清除:应用终止场景 ........................ 23

2.3 设置产品属性 ....................................................... 23 2.3.1 Xcode 中的工程和目标 ............................. 23 2.3.2 设置常用的产品属性 ................................ 26

2.4 iOS API 简介 ......................................................... 27 2.4.1 API 概述 .................................................... 27 2.4.2 如何使用 API 帮助 ................................... 29

2.5 小结 ....................................................................... 32

第 3 章 Cocoa Touch框架与构建应用界面 .......... 33 3.1 视图控制器 ........................................................... 33

3.1.1 视图控制器种类 ........................................ 33 3.1.2 视图的生命周期 ........................................ 33

3.2 视图 ....................................................................... 35 3.2.1 UIView继承层次结构................................ 35 3.2.2 视图分类.................................................... 37 3.2.3 应用界面构建层次 .................................... 37

3.3 使用故事板构建界面 ............................................ 38 3.3.1 什么是故事板 ............................................ 39 3.3.2 场景和过渡 ................................................ 41

3.4 使用 XIB 文件构建界面 ....................................... 42 3.4.1 重构 HelloWorld ........................................ 42 3.4.2 XIB 与故事板比较 .................................... 45

3.5 使用纯代码构建界面 ............................................ 45 3.5.1 重构 HelloWorld ........................................ 46 3.5.2 视图的几个重要属性 ................................ 47

3.6 3 种构建界面技术讨论 ......................................... 49 3.6.1 所见即所得 ................................................ 49 3.6.2 原型驱动开发 ............................................ 49 3.6.3 团队协同开发 ............................................ 49

3.7 小结 ....................................................................... 50

第 4 章 UIView与视图 ............................................. 51 4.1 标签与按钮 ........................................................... 51

4.1.1 Interface Builder 实现 ................................ 51 4.1.2 代码实现.................................................... 55

4.2 事件处理 ............................................................... 56 4.2.1 Interface Builder 实现 ................................ 56 4.2.2 代码实现.................................................... 59

4.3 访问视图 ............................................................... 60 4.3.1 Interface Builder 实现 ................................ 60 4.3.2 代码实现.................................................... 62

4.4 TextField 和 TextView .......................................... 63 4.4.1 Interface Builder 实现 ................................ 64 4.4.2 代码实现.................................................... 65 4.4.3 键盘的打开和关闭 .................................... 67 4.4.4 关闭和打开键盘的通知 ............................ 68 4.4.5 键盘的种类 ................................................ 69

4.5 开关控件、分段控件和滑块控件 ........................ 70 4.5.1 开关控件.................................................... 71

Page 7: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

2 目 录

4.5.2 分段控件 ................................................... 72 4.5.3 滑块控件 ................................................... 74

4.6 Web 视图:WKWebView类 ..................................... 76 4.7 警告框和操作表 ................................................... 80

4.7.1 UIAlertController实现警告框 ............... 81 4.7.2 UIAlertController实现操作表 ............... 83

4.8 等待相关的控件与进度条 .................................... 84 4.8.1 活动指示器 ActivityIndicatorView ........... 85 4.8.2 进度条 ProgressView ................................ 87

4.9 工具栏和导航栏 ................................................... 90 4.9.1 工具栏 ....................................................... 90 4.9.2 导航栏 ....................................................... 94

4.10 小结 ..................................................................... 98

第 5 章 委托协议、数据源协议与高级视图 ........ 99 5.1 视图中的委托协议和数据源协议 ........................ 99 5.2 选择器 ................................................................... 99

5.2.1 日期选择器................................................ 99 5.2.2 普通选择器.............................................. 104 5.2.3 数据源协议与委托协议 .......................... 109

5.3 集合视图 ............................................................. 111 5.4 实例:Interface Builder 实现奥运会比赛

项目 ..................................................................... 112 5.4.1 添加集合视图 .......................................... 113 5.4.2 添加集合视图单元格 .............................. 114 5.4.3 数据源协议与委托协议 .......................... 118

5.5 实例:代码实现奥运会比赛项目 ...................... 120 5.5.1 添加集合视图 .......................................... 120 5.5.2 自定义集合视图单元格 .......................... 122

5.6 小结 ..................................................................... 123

第 6 章 表视图 ...................................................... 124 6.1 概述 ..................................................................... 124

6.1.1 表视图的组成 .......................................... 124 6.1.2 表视图的相关类 ...................................... 125 6.1.3 表视图分类.............................................. 125 6.1.4 单元格的组成和样式 .............................. 127 6.1.5 数据源协议与委托协议 .......................... 129

6.2 简单表视图 ......................................................... 129 6.2.1 实现协议方法 .......................................... 130 6.2.2 UIViewController根视图控制器 ........... 130 6.2.3 UITableViewController根视图

控制器 ..................................................... 137 6.3 自定义表视图单元格 .......................................... 140

6.3.1 Interface Builder 实现 .............................. 141

6.3.2 代码实现 ................................................. 145 6.4 添加搜索栏 ......................................................... 146 6.5 分节表视图 ......................................................... 150

6.5.1 添加索引 ................................................. 150 6.5.2 分组 ......................................................... 153

6.6 静态表与界面布局 .............................................. 154 6.7 插入和删除单元格 .............................................. 160

6.7.1 Interface Builder 实现 .............................. 162 6.7.2 代码实现 ................................................. 167

6.8 移动单元格 ......................................................... 169 6.9 表视图 UI 设计模式 ............................................ 171

6.9.1 分页模式 ................................................. 171 6.9.2 下拉刷新模式 .......................................... 171 6.9.3 下拉刷新控件 .......................................... 172

6.10 小结 ................................................................... 174

第 7 章 界面布局与屏幕适配 .............................. 175 7.1 界面布局概述 ..................................................... 175 7.2 iOS 界面布局设计模式 ....................................... 176

7.2.1 表单布局模式 .......................................... 176 7.2.2 列表布局模式 .......................................... 176 7.2.3 网格布局模式 .......................................... 177

7.3 传统布局技术 ..................................................... 177 7.4 Auto Layout 布局技术 ........................................ 179

7.4.1 Interface Builder 中管理 Auto Layout

约束 ......................................................... 179 7.4.2 实例:Auto Layout 布局 ......................... 180

7.5 iOS 9 堆视图 StackView ..................................... 185 7.5.1 堆视图与布局 .......................................... 185 7.5.2 实例:堆视图布局 .................................. 186

7.6 iOS 屏幕的多样性 .............................................. 191 7.6.1 iOS 屏幕介绍 ........................................... 191 7.6.2 iOS 的 3 种分辨率 ................................... 192 7.6.3 获得 iOS 设备屏幕信息 .......................... 193

7.7 Size Class 与 iOS 多屏幕适配 ............................ 194 7.7.1 Interface Builder 中使用 Size Class ........ 195 7.7.2 Size Class 的九宫格 ................................ 195 7.7.3 实例:使用 Size Class ............................ 196

7.8 资源目录与图片资源适配 .................................. 201 7.9 小结 ..................................................................... 204

第 8 章 视图控制器与导航模式 .......................... 205 8.1 概述 ..................................................................... 205

8.1.1 视图控制器的种类 .................................. 205 8.1.2 导航模式 ................................................. 205

Page 8: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

目 录 3

8.2 模态视图 ............................................................. 207 8.2.1 Interface Builder 实现 .............................. 208 8.2.2 代码实现 ................................................. 214

8.3 平铺导航 ............................................................. 215 8.3.1 应用场景 ................................................. 215 8.3.2 基于分屏导航的实现 .............................. 217 8.3.3 基于电子书导航的实现 .......................... 223

8.4 标签导航 ............................................................. 228 8.4.1 应用场景 ................................................. 229 8.4.2 Interface Builder 实现 .............................. 230 8.4.3 代码实现 ................................................. 234

8.5 树形结构导航 ..................................................... 235 8.5.1 应用场景 ................................................. 235 8.5.2 Interface Builder 实现 .............................. 236 8.5.3 代码实现 ................................................. 244

8.6 组合使用导航模式 .............................................. 245 8.6.1 应用场景 ................................................. 246 8.6.2 Interface Builder 实现 .............................. 246 8.6.3 代码实现 ................................................. 254

8.7 小结 ..................................................................... 257

第 9 章 iPad 应用开发 ......................................... 258 9.1 iPad 与 iPhone 应用开发的差异 ......................... 258

9.1.1 应用场景不同 .......................................... 258 9.1.2 导航模式不同 .......................................... 258 9.1.3 API 不同 .................................................. 258

9.2 iPad 树形结构导航 .............................................. 259 9.2.1 邮件应用中的树形结构导航 .................. 259 9.2.2 Master-Detail 应用程序模板 ................... 260 9.2.3 Interface Builder 实现 SplitViewSample

案例 ......................................................... 266 9.2.4 代码实现 SplitViewSample 案例 ............ 270

9.3 iPad 模态视图 ...................................................... 273 9.3.1 邮件应用中的模态导航 .......................... 273 9.3.2 iPad 模态导航相关 API .......................... 275 9.3.3 Interface Builder 实现 ModalView-

Sample 案例............................................. 277 9.3.4 代码实现 ModalViewSample 案例 ......... 281

9.4 Popover(浮动层)视图 .................................... 284 9.4.1 Popover 相关 API .................................... 284 9.4.2 PopoverViewSample 案例 ....................... 285

9.5 iOS 9 分屏多任务................................................ 289 9.5.1 Slide Over 多任务 .................................... 289 9.5.2 分屏视图多任务 ...................................... 290 9.5.3 画中画多任务 .......................................... 293

9.6 iPad 分屏多任务适配开发 .................................. 293 9.6.1 分屏多任务前提条件 .............................. 293 9.6.2 分屏多任务适配 ...................................... 294

9.7 小结 ..................................................................... 295

第二部分 设计与架构篇

第 10 章 iOS 常用设计模式 ................................ 298 10.1 单例模式 ........................................................... 298

10.1.1 问题提出 .............................................. 298 10.1.2 Objective-C 实现原理 ......................... 298 10.1.3 Swift 实现原理 .................................... 299 10.1.4 应用案例 .............................................. 300

10.2 委托模式 ........................................................... 301 10.2.1 问题提出 .............................................. 301 10.2.2 实现原理 .............................................. 303 10.2.3 应用案例 .............................................. 306

10.3 观察者模式 ....................................................... 309 10.3.1 问题提出 .............................................. 309 10.3.2 实现原理 .............................................. 310 10.3.3 通知机制和 KVO 机制 ....................... 311

10.4 再谈 MVC 模式 ................................................. 317 10.4.1 MVC 模式概述 .................................... 317 10.4.2 Cocoa Touch 中的 MVC 模式 ............. 318

10.5 小结 ................................................................... 320

第 11 章 iOS 分层架构设计 ................................ 321 11.1 低耦合企业级系统架构设计 ............................ 321 11.2 iOS 分层架构设计 ............................................. 322

11.2.1 工程与工作空间 .................................. 322 11.2.2 静态链接库 .......................................... 323 11.2.3 框架 ..................................................... 323 11.2.4 16 种分层模式 ..................................... 324

11.3 实例:MyNotes 应用 ........................................ 325 11.4 基于同一工程的分层 ........................................ 327

11.4.1 采用纯 Swift 语言实现:PSSS

模式 ..................................................... 327 11.4.2 采用纯 Objective-C 语言实现:

POOO 模式 .......................................... 330 11.4.3 采用 Swift 调用 Objective-C 的

混合搭配实现:PSOO 模式 ............... 334 11.5 基于同一工作空间静态链接库实现的 WLSOO

模式 ................................................................... 335 11.5.1 使用工作空间 ...................................... 335 11.5.2 添加数据持久层工程 .......................... 336

Page 9: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

4 目 录

11.5.3 建立业务逻辑层与数据持久层依赖

关系 ..................................................... 337 11.5.4 建立表示层与业务逻辑层依赖

关系 ..................................................... 339 11.6 基于同一工作空间框架实现的 WFSSS

模式 ................................................................... 339 11.6.1 创建框架工程 ...................................... 340 11.6.2 建立依赖关系 ...................................... 341 11.6.3 代码重构.............................................. 342

11.7 基于同一工作空间框架实现的 WFOOO

模式 ................................................................... 344 11.7.1 设置 Public 头文件 .............................. 344 11.7.2 设置保护伞头文件 .............................. 345 11.7.3 代码重构.............................................. 345

11.8 基于同一工作空间框架实现的 WFSOO

模式 ................................................................... 346 11.8.1 设置 Public 头文件 .............................. 346 11.8.2 设置保护伞头文件 .............................. 346 11.8.3 建立表示层与业务逻辑层依赖

关系 ..................................................... 346 11.8.4 代码重构.............................................. 346

11.9 基于同一工作空间框架实现的 WFOSS

模式 ................................................................... 346 11.9.1 设置 Public 头文件 .............................. 346 11.9.2 设置 Swift 代码嵌入应用 ................... 347 11.9.3 代码重构.............................................. 347

11.10 基于同一个工程不同目标框架实现的

TFSOO 模式 .................................................... 348 11.10.1 使用目标 .......................................... 348 11.10.2 添加框架目标 .................................. 348

11.11 小结 ................................................................. 349

第 12 章 数据持久化 ............................................ 350 12.1 概述 ................................................................... 350

12.1.1 沙箱目录.............................................. 350 12.1.2 持久化方式 .......................................... 351

12.2 属性列表 ........................................................... 351 12.3 对象归档 ........................................................... 357 12.4 使用 SQLite 数据库 .......................................... 361

12.4.1 SQLite 数据类型 ................................. 361 12.4.2 配置 Objective-C 框架工程环境 ......... 362 12.4.3 配置 Swift 框架工程环境 ................... 362 12.4.4 创建数据库 .......................................... 364 12.4.5 查询数据.............................................. 365 12.4.6 修改数据.............................................. 368

12.5 Core Data ........................................................... 370 12.5.1 ORM .................................................... 370 12.5.2 Core Data 栈 ........................................ 371 12.5.3 建模和生成实体 .................................. 374 12.5.4 采用 Core Data 分层架构设计 ............ 380 12.5.5 查询数据 .............................................. 382 12.5.6 修改数据 .............................................. 384

12.6 小结 ................................................................... 385

第三部分 进 阶 篇

第 13 章 应用程序设置 ........................................ 388 13.1 概述 ................................................................... 388

13.1.1 设置 ..................................................... 388 13.1.2 配置 ..................................................... 389

13.2 应用程序设置包 ................................................ 390 13.3 设置项目种类 ................................................... 392

13.3.1 文本字段 .............................................. 395 13.3.2 开关 ..................................................... 398 13.3.3 滑块 ..................................................... 399 13.3.4 值列表 ................................................. 400 13.3.5 子界面 ................................................. 401

13.4 读取设置 ........................................................... 403 13.5 小结 ................................................................... 405

第 14 章 本地化 .................................................... 406 14.1 概述 ................................................................... 406

14.1.1 需要本地化的内容 .............................. 406 14.1.2 本地化目录结构 .................................. 409

14.2 文本信息本地化 ................................................ 410 14.2.1 系统按钮和信息本地化 ...................... 410 14.2.2 应用名称本地化 .................................. 411 14.2.3 程序代码输出的静态文本本地化 ...... 413 14.2.4 使用 genstring 工具 ............................. 414

14.3 故事板和 XIB 文件本地化 ............................... 415 14.3.1 使用 Base Internationalization 技术 .... 415 14.3.2 Auto Layout 与本地化 ......................... 417

14.4 资源文件本地化 ................................................ 419 14.4.1 图片资源文件本地化 .......................... 419 14.4.2 声音资源文件本地化 .......................... 420

14.5 小结 ................................................................... 421

第 15 章 iOS 9 中访问通讯录 ............................. 422 15.1 通讯录的安全访问设置 .................................... 422 15.2 使用 Contacts框架读取联系人信息 ................. 423

Page 10: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

目 录 5

15.2.1 查询联系人 .......................................... 423 15.2.2 读取单值属性 ...................................... 426 15.2.3 读取多值属性 ...................................... 428 15.2.4 读取图片属性 ...................................... 430

15.3 使用 Contacts框架写入联系人信息 ................. 430 15.3.1 创建联系人 .......................................... 431 15.3.2 修改联系人 .......................................... 433 15.3.3 删除联系人 .......................................... 434

15.4 使用系统提供界面 ............................................ 435 15.4.1 选择联系人 .......................................... 435 15.4.2 显示和修改联系人 .............................. 438 15.4.3 创建联系人 .......................................... 441

15.5 小结 ................................................................... 444

第 16 章 数据交换格式 ....................................... 445 16.1 XML 数据交换格式 .......................................... 446

16.1.1 XML 文档结构 .................................... 446 16.1.2 解析 XML 文档 ................................... 447

16.2 实例:MyNotes 应用 XML .............................. 448 16.2.1 使用 NSXML 解析 .............................. 450 16.2.2 使用 TBXML 解析 .............................. 453

16.3 JSON 数据交换格式 ......................................... 459 16.3.1 JSON 文档结构 ................................... 459 16.3.2 JSON 数据编码/解码 .......................... 460

16.4 实例:MyNotes 应用 JSON 解码 ..................... 461 16.5 小结 ................................................................... 462

第 17 章 REST Web Service ............................. 463 17.1 概述 ................................................................... 463 17.2 使用 NSURLSession ......................................... 464

17.2.1 NSURLSession API ............................. 464 17.2.2 简单会话实现 GET请求 ...................... 465 17.2.3 默认会话实现 GET请求 ...................... 468 17.2.4 实现 POST请求 .................................... 469 17.2.5 下载数据 .............................................. 470

17.3 实例:使用 NSURLSession重构 MyNotes

案例 ................................................................... 473 17.3.1 插入方法调用 ...................................... 473 17.3.2 修改方法调用 ...................................... 474 17.3.3 删除方法调用 ...................................... 475

17.4 使用 AFNetworking 框架 .................................. 477 17.4.1 比较 ASIHTTPRequest、

AFNetworking 和 MKNetworkKit ...... 477 17.4.2 安装和配置 AFNetworking框架 .......... 478 17.4.3 实现 GET请求 ...................................... 479

17.4.4 实现 POST请求 .................................... 480 17.4.5 下载数据 .............................................. 481 17.4.6 上传数据 .............................................. 482

17.5 使用为 Swift 设计的网络框架:

Alamofire ........................................................... 484 17.5.1 安装和配置 Alamofire框架 ................. 484 17.5.2 实现 GET请求 ...................................... 485 17.5.3 实现 POST请求 .................................... 486 17.5.4 下载数据 .............................................. 487 17.5.5 上传数据 .............................................. 488

17.6 反馈网络信息改善用户体验 ............................ 489 17.6.1 使用下拉刷新控件改善用户体验 ...... 489 17.6.2 使用活动指示器控件 .......................... 492 17.6.3 使用网络活动指示器 .......................... 494

17.7 小结 ................................................................... 494

第 18 章 定位服务 ............................................... 495 18.1 定位服务概述.................................................... 495

18.1.1 定位服务编程 ...................................... 496 18.1.2 测试定位服务 ...................................... 499

18.2 管理定位服务.................................................... 503 18.2.1 应用启动与停止下的定位服务

管理 ..................................................... 504 18.2.2 视图切换下的定位服务管理 .............. 504 18.2.3 应用前后台切换下的定位服务

管理 ..................................................... 505 18.2.4 设置自动暂停位置服务 ...................... 507 18.2.5 iOS 9 后台位置服务管理 .................... 507

18.3 地理信息编码与反编码 .................................... 508 18.3.1 地理信息反编码 .................................. 508 18.3.2 实例:地理信息反编码 ...................... 509 18.3.3 地理信息编码查询 .............................. 510 18.3.4 实例:地理信息编码查询 .................. 510

18.4 微定位技术 iBeacon .......................................... 512 18.4.1 微定位与地理围栏 .............................. 512 18.4.2 iBeacon 技术概述 ................................ 512 18.4.3 实例:使用 iBeacon 技术实现微

定位 ..................................................... 513 18.5 小结 ................................................................... 519

第 19 章 苹果地图应用........................................ 520 19.1 使用 iOS 苹果地图 ............................................ 520

19.1.1 显示地图 .............................................. 520 19.1.2 显示 3D 地图 ....................................... 524

19.2 添加标注 ........................................................... 525

Page 11: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

6 目 录

19.2.1 实现查询.............................................. 526 19.2.2 在地图上添加标注 .............................. 528

19.3 跟踪用户位置变化 ............................................ 529 19.4 使用程序外地图................................................ 530 19.5 小结 ................................................................... 533

第四部分 测试、调试和优化篇

第 20 章 找出程序中的 bug——调试 ................ 536 20.1 Xcode 调试工具 ................................................ 536

20.1.1 定位编译错误 ...................................... 536 20.1.2 查看和显示日志 .................................. 537 20.1.3 设置和查看断点 .................................. 539 20.1.4 调试工具.............................................. 544 20.1.5 输出窗口.............................................. 545 20.1.6 变量查看窗口 ...................................... 546 20.1.7 查看线程.............................................. 547

20.2 LLDB 调试工具 ................................................ 548 20.2.1 断点命令.............................................. 548 20.2.2 观察点命令 .......................................... 550 20.2.3 查看变量和计算表达式命令 .............. 552

20.3 日志与断言输出................................................ 554 20.3.1 使用 NSLog函数 .................................. 554 20.3.2 使用断言.............................................. 555

20.4 异常栈报告分析................................................ 556 20.4.1 跟踪异常栈 .......................................... 556 20.4.2 分析栈报告 .......................................... 558

20.5 在 iOS 设备上调试 ............................................ 559 20.5.1 Xcode 设置 .......................................... 559 20.5.2 设备设置.............................................. 560

20.6 Xcode 设备管理工具 ........................................ 562 20.6.1 查看设备上的应用程序 ...................... 562 20.6.2 设备日志.............................................. 564

20.7 小结 ................................................................... 564

第 21 章 iOS 测试驱动与单元测试 .................... 565 21.1 测试驱动的软件开发概述 ................................ 565

21.1.1 测试驱动的软件开发流程 .................. 565 21.1.2 测试驱动的软件开发案例 .................. 566 21.1.3 iOS 单元测试框架 ............................... 567

21.2 使用 XCTest 测试框架 ..................................... 568 21.2.1 添加 XCTest 到工程............................ 568 21.2.2 Swift 版本中设置编译目标成员 ......... 570 21.2.3 编写 XCTest 测试方法 ........................ 570 21.2.4 运行测试用例目标 .............................. 573

21.2.5 分析测试报告 ...................................... 575 21.3 异步单元测试 ................................................... 576 21.4 性能测试 ........................................................... 580

21.4.1 Swift 版本中配置测试环境 ................ 580 21.4.2 测试用例代码 ...................................... 580 21.4.3 分析测试结果 ...................................... 581

21.5 iOS 单元测试最佳实践 ..................................... 583 21.5.1 配置测试数据持久层 .......................... 583 21.5.2 编写数据持久层测试用例 .................. 584 21.5.3 运行测试数据持久层测试用例 .......... 587 21.5.4 配置测试业务逻辑层 .......................... 588 21.5.5 编写业务逻辑层测试用例 .................. 588

21.6 小结 ................................................................... 589

第 22 章 iOS 应用 UI 测试 ................................... 590 22.1 UI 测试概述 ...................................................... 590 22.2 添加 UI 测试到工程 .......................................... 590

22.2.1 创建工程时添加 UI测试框架 ............ 590 22.2.2 在现有工程中添加 UI 测试用例

目标 ..................................................... 591 22.3 录制脚本 ........................................................... 593

22.3.1 录制之前的准备 .................................. 593 22.3.2 录制过程 .............................................. 593 22.3.3 修改录制脚本 ...................................... 595

22.4 访问 UI 元素 ..................................................... 595 22.4.1 UI 元素层次结构树 ............................. 595 22.4.2 UI 测试中相关 API ............................. 597

22.5 表示层测试最佳实践 ........................................ 598 22.5.1 配置 UI 测试用例目标 ........................ 598 22.5.2 编写 UI 测试用例 ................................ 599

22.6 小结 ................................................................... 602

第 23 章 让你的程序“飞”起来——性能 优化 ........................................................ 603

23.1 内存优化 ........................................................... 603 23.1.1 内存管理 .............................................. 603 23.1.2 使用 Analyze 工具检查内存泄漏 ....... 603 23.1.3 使用 Instruments 工具检查内存

泄漏 ..................................................... 608 23.1.4 使用 Instruments 工具检查僵尸

对象 ..................................................... 612 23.1.5 autorelease 的使用问题 ....................... 615 23.1.6 响应内存警告 ...................................... 616

23.2 优化资源文件 ................................................... 617 23.2.1 图片文件优化 ........................................ 618

Page 12: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

目 录 7

23.2.2 音频文件优化 ...................................... 619 23.3 延迟加载 ........................................................... 620

23.3.1 资源文件的延迟加载 .......................... 620 23.3.2 故事板文件的延迟加载 ...................... 624 23.3.3 XIB 文件的延迟加载 .......................... 626

23.4 数据持久化的优化 ............................................ 628 23.4.1 使用文件 .............................................. 628 23.4.2 使用 SQLite 数据库 ............................ 631 23.4.3 使用 Core Data .................................... 632

23.5 可重用对象的使用 ............................................ 634 23.5.1 表视图中的可重用对象 ...................... 635 23.5.2 集合视图中的可重用对象 .................. 636 23.5.3 地图视图中的可重用对象 .................. 638

23.6 并发处理与多核 CPU ....................................... 638 23.6.1 主线程阻塞问题 .................................. 638 23.6.2 选择 NSThread 还是 GCD .................. 639

23.7 小结 ................................................................... 640

第五部分 实 战 篇

第 24 章 管理好你的程序代码——代码版本 控制 .............................................................. 642

24.1 概述 ................................................................... 642 24.1.1 版本控制历史 ...................................... 642 24.1.2 基本概念 .............................................. 643

24.2 Git 代码版本控制 .............................................. 643 24.2.1 服务器搭建 .......................................... 643 24.2.2 Gitolite 服务器管理 ............................. 645 24.2.3 Git 常用命令 ........................................ 647 24.2.4 Git 分支 ................................................ 649 24.2.5 Git 协同开发 ........................................ 653 24.2.6 Xcode 中 Git 的配置与使用 ................ 656

24.3 GitHub 代码托管服务 ....................................... 663 24.3.1 创建和配置 GitHub 账号 .................... 663 24.3.2 创建代码库 .......................................... 666 24.3.3 删除代码库 .......................................... 668 24.3.4 派生代码库 .......................................... 669 24.3.5 使用 GitHub 协同开发 ........................ 671 24.3.6 管理组织 .............................................. 677

24.4 小结 ................................................................... 680

第 25 章 项目依赖管理 ....................................... 681 25.1 使用 CocoaPods 工具管理依赖 ........................ 681

25.1.1 安装 CocoaPods ................................... 681

25.1.2 搜索库.................................................. 682 25.1.3 项目与第三方库搭配形式 .................. 683 25.1.4 示例:静态链接库形式管理依赖 ...... 684 25.1.5 示例:框架形式管理依赖 .................. 686

25.2 使用 Carthage 工具管理依赖 ............................ 687 25.2.1 安装 Carthage ...................................... 688 25.2.2 项目与第三方库搭配形式 .................. 688 25.2.3 Cartfile 文件 ......................................... 688 25.2.4 示例:重构 MyNotes 依赖关系 ......... 689

25.3 小结 ................................................................... 691

第 26 章 重构 MyNotes 应用——iOS 网络 通信中的设计模式与架构设计 ............ 692

26.1 移动网络通信应用的分层架构设计 ................ 692 26.2 Objective-C 版本:在数据持久层中添加和

配置 AFNetworking .......................................... 693 26.2.1 用 CocoaPods 工具管理依赖 .............. 693 26.2.2 测试依赖 .............................................. 693

26.3 Swift 版本:在数据持久层中添加和配置

Alamofire ........................................................... 694 26.3.1 用 Carthage 工具管理依赖 .................. 694 26.3.2 测试依赖 .............................................. 695

26.4 基于委托模式实现 ............................................ 695 26.4.1 网络通信与委托模式 .......................... 696 26.4.2 在异步网络通信中使用委托模式

实现分层架构设计 .............................. 696 26.4.3 类图 ..................................................... 697 26.4.4 时序图.................................................. 699 26.4.5 数据持久层重构(Objective-C

版本) ................................................. 702 26.4.6 数据持久层重构(Swift 版本) ......... 705 26.4.7 业务逻辑层的代码实现 ...................... 707 26.4.8 表示层的代码实现 .............................. 710

26.5 基于观察者模式的通知机制实现 .................... 716 26.5.1 观察者模式的通知机制回顾 .............. 716 26.5.2 异步网络通信中通知机制的分层架

构设计 ................................................. 716 26.5.3 类图 ..................................................... 717 26.5.4 时序图.................................................. 719 26.5.5 数据持久层重构(Objective-C

版本) ................................................. 722 26.5.6 数据持久层重构(Swift 版本) ......... 723 26.5.7 业务逻辑层的代码实现 ...................... 725 26.5.8 表示层的代码实现 .............................. 726

26.6 小结 ................................................................... 731

Page 13: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

8 目 录

第 27 章 把你的应用放到 App Store 上 ............. 732 27.1 收官 ................................................................... 732

27.1.1 在 Xcode 中添加图标 ......................... 732 27.1.2 在 Xcode 中添加启动界面 .................. 734 27.1.3 调整 Identity 和 Deployment Info

属性 ..................................................... 738 27.2 为发布进行编译................................................ 739

27.2.1 创建开发者证书 .................................. 739 27.2.2 创建 App ID ........................................ 744 27.2.3 创建描述文件 ...................................... 745 27.2.4 发布编译.............................................. 748

27.3 发布上架 ........................................................... 750 27.3.1 创建应用.............................................. 750 27.3.2 应用定价.............................................. 753 27.3.3 基本信息输入 ...................................... 754 27.3.4 上传应用.............................................. 757 27.3.5 提交审核.............................................. 759

27.4 常见审核不通过的原因 .................................... 761 27.4.1 功能问题.............................................. 761 27.4.2 用户界面问题 ...................................... 761 27.4.3 商业问题.............................................. 761 27.4.4 不当内容.............................................. 761 27.4.5 其他问题.............................................. 762

27.5 小结 ................................................................... 762

第 28 章 iOS 敏捷开发项目实战——2016 里 约热内卢奥运会应用开发及 App Store发布 ........................................................ 763

28.1 应用分析与设计................................................ 763 28.1.1 应用概述.............................................. 763 28.1.2 需求分析.............................................. 763 28.1.3 原型设计.............................................. 764 28.1.4 数据库设计 .......................................... 765 28.1.5 架构设计.............................................. 766

28.2 iOS 敏捷开发 .................................................... 766 28.2.1 敏捷开发宣言 ...................................... 766 28.2.2 iOS 适合敏捷开发? ........................... 767 28.2.3 iOS 敏捷开发最佳实践 ....................... 767

28.3 任务 1:创建应用工作空间和工程 ................. 769 28.3.1 迭代 1.1:创建工作空间 .................... 769 28.3.2 迭代 1.2:发布到 GitHub ................... 769

28.4 任务 2:信息系统层与持久层开发 ................. 770 28.4.1 迭代 2.1:编写数据库 DDL 脚本 ...... 770

28.4.2 迭代 2.2:插入初始数据到数据库 .... 770 28.4.3 迭代 2.3:数据库版本控制 ................ 771 28.4.4 迭代 2.4:配置持久层工程

PersistenceLayer .................................. 771 28.4.5 迭代 2.5:编写实体类 ........................ 772 28.4.6 迭代 2.6:编写 DAO 类单元测试用

例类 ..................................................... 773 28.4.7 迭代 2.7:编写 DAO 类 ..................... 775 28.4.8 迭代 2.8:数据库帮助类 DBHelper .... 779 28.4.9 迭代 2.9:配置及运行持久层测试用

例目标 ................................................. 781 28.4.10 迭代 2.10:发布到 GitHub ............... 782

28.5 任务 3:业务逻辑层开发 ................................. 782 28.5.1 迭代 3.1:比赛项目业务逻辑类

XCTest 单元测试 ................................ 783 28.5.2 迭代 3.2:编写比赛项目业务

逻辑类 ................................................. 784 28.5.3 迭代 3.3:比赛日程业务逻辑类

XCTest 单元测试 ................................ 785 28.5.4 迭代 3.4:编写比赛日程业务

逻辑类 ................................................. 786 28.5.5 迭代 3.5:发布到 GitHub ................... 787

28.6 任务 4:表示层开发 ......................................... 788 28.6.1 迭代 4.1:使用资源目录管理图片和

图标资源 ............................................. 788 28.6.2 迭代 4.2:根据原型设计初步设计

故事板 ................................................. 789 28.6.3 迭代 4.3:“首页”模块 .................... 790 28.6.4 迭代 4.4:“比赛项目”模块 ............ 791 28.6.5 迭代 4.5:“比赛日程”模块 ............ 795 28.6.6 迭代 4.6:“倒计时”模块

表示层 ................................................. 797 28.6.7 迭代 4.7:“关于我们”模块

表示层 ................................................. 800 28.6.8 迭代 4.8:发布到 GitHub ................... 800

28.7 任务 5:收工 .................................................... 800 28.7.1 迭代 5.1:添加图标 ............................ 800 28.7.2 迭代 5.2:设计和添加启动界面 ........ 801 28.7.3 迭代 5.3:性能测试与改善 ................ 801 28.7.4 迭代 5.4:发布到 GitHub 上 .............. 802 28.7.5 迭代 5.5:在 App Store 上发布

应用 ..................................................... 802 28.8 小结 ................................................................... 802

Page 14: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

590 第 22 章 iOS 应用 UI 测试

iOS应用UI测试

我们已经在前一章介绍了苹果iOS单元测试框架XCTest,苹果在iOS 9之后在XCTest框架的基础上增加了UI

测试API,并且在Xcode 7之后提供了UI测试工具。

22.1 UI 测试概述

UI测试从来都是开发人员和测试人员的梦魇,它是 麻烦的。UI测试的过程涉及很多方面,包括UI事件处

理、表示逻辑、控件输入验证和获取UI环境对象,其中 困难的是获取UI环境对象。例如,在使用故事板的iOS

应用中,视图控制器和视图等UI对象不是在测试程序中创建的,而是由运行环境通过故事板创建的,如果直接实

例化它们,会丢失很多状态。

要解决这种尴尬的局面,只能改善测试方法,提高工具的易用性。由于UI测试用例都是围绕界面操作而设计

的,一些测试工具可以将这些操作录制下来,生成测试代码,测试人员可以适当修改测试代码,使之能够适用于

更加普通的情况,然后就可以运行这些测试程序,出具测试报告。这就是“自动化测试”,测试代码被称为“测

试脚本”。

事实上,苹果提供了两种自动化测试框架:UIAutomation框架和iOS 9之后的XCTest测试框架。UIAutomation

框架是在iOS 4之后发布的,但是至今仍然鲜为人知,很少人使用。这主要是因为它非常难用,使用时要结合使

用Xcode的Instruments工具,它所录制生成的脚本是JavaScript语言的,测试人员还要学习JavaScript语法形式的

UIAutomation API。Xcode 7之后提供的UI测试功能,可以生成Objective-C或Swift语言的测试脚本,新增的API是

基于XCTest的,提供了Objective-C和Swift两种语言支持。

本章重点介绍如何使用iOS 9的XCTest测试框架实现UI测试。为了方便,本书将iOS 9新增的XCTest测试框架

中的UI测试相关部分称为UI测试框架。

22.2 添加 UI 测试到工程

使用Xcode 7工具添加UI测试框架到工程中,有两种方法:一种是在创建工程时添加;另一种是在现有工程

中添加iOS UI Testing Bundle目标(Target)。下面我们详细介绍一下这两种方法。

22.2.1 创建工程时添加 UI 测试框架

使用Xcode 7创建工程时,在创建工程信息对话框(如图22-1所示)中,选中Include UI Tests,这会使在创建

工程目标的同时,创建一个UI测试用例目标。如图22-2所示,在生成的Xcode导航面板中,有一个PITaxUITests

组,这个组中的类就是生成的测试类,并且还在目标列表中生成了测试PITaxUITests目标。

第 22 章

Page 15: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

22.2 添加 UI 测试到工程 591

图22-1 创建工程信息对话框

图22-2 添加完成的UI测试用例目标

22.2.2 在现有工程中添加 UI 测试用例目标

在一个现有的工程中,选择File→New→Target…菜单项,此时打开的界面如图22-3所示,从中选择iOS→Test

中的iOS UI Testing Bundle模板。点击Next按钮,进入下一个目标相关项界面,如图22-4所示,在Product Name中

输入PITaxUITests;Language中选择语言,原则上要测试的类使用何种语言,测试用例类也应该采用这种语言;

Project中选择我们当前的测试工程,Target to be Tested中选择要测试的目标。

图22-3 选择模板

Page 16: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

592 第 22 章 iOS 应用 UI 测试

图22-4 为现有工程添加测试用例目标

设置完相关项后,点击Finish按钮创建测试用例目标。添加完成后的工程如图22-5所示,此时在导航面板中

多出了一个PITaxUITests目标。

图22-5 添加测试用例目标之后的工程

无论哪种方式,默认生成的UI测试用例类基本都是一样的。下面的代码是UI测试用例PITaxUITests目标默认

生成的PITaxUITests测试用例类:

//PITaxUITests.swift文件

import XCTest

class PITaxUITests: XCTestCase {

override func setUp() {

super.setUp()

//测试用例出错后是否继续执行,设置为true表示继续执行,设置为false

//表示终止

continueAfterFailure = false

//UI测试必须启动应用,该语句可以启动应用程序

XCUIApplication().launch()

}

override func tearDown() {

super.tearDown()

}

func testExample() {

}

//PITaxUITests.m文件

#import <XCTest/XCTest.h>

@interface PITaxUITests : XCTestCase

@end

@implementation PITaxUITests

- (void)setUp {

[super setUp];

//测试用例出错后是否继续执行,设置为true表示继续执行,设置为false表示

//终止

//self.continueAfterFailure = NO;

//UI测试必须启动应用,该语句可以启动应用程序

[[[XCUIApplication alloc] init] launch];

}

- (void)tearDown {

[super tearDown];

}

Page 17: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

22.3 录制脚本 593

}

- (void)testExample {

}

@end

从上述代码可见,UI测试用例类与单元测试用例类非常类似。

22.3 录制脚本

Xcode 7提供测试脚本录制工具UI Recording,通过该工具可以生成Objective-C或Swift语言的测试脚本。

22.3.1 录制之前的准备

下面我们为PITax案例的UI测试用例目标PITaxUITests录制脚本。在开始录制脚本之前,我们需要为界面中的

控件添加“辅助功能①”,苹果为“辅助功能”开发提供一套API,我们现在使用的UI测试框架基于辅助功能和XCTest

两种技术。辅助功能提供了访问界面中UI元素的能力。在Interface Builder中打开故事板或XIB文件,如图22-6所

示,选中控件,然后打开右边的标识检查器,在Accessibility→ Label中设置控件的标签。此外,也可以设置Identifier

(标识)属性。

本例中,我们只需要设置Txt Revenue文本框的标签属性为TextField Revenue,计算按钮的标签属性为Calculate

Button。

图22-6 设置辅助功能属性

22.3.2 录制过程

下面我们可以开始录制了。打开PITaxUITests测试用例类,如图22-7所示,将光标置于测试方法中,UI

—————————— ① 辅助功能是指软件为残障人士提供了一些特殊功能,如屏幕放大和语音提示等功能。

Page 18: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

594 第 22 章 iOS 应用 UI 测试

Recording会在这里生成代码。然后,点击调试栏中的“录制”按钮 开始录制。

图22-7 开始录制脚本

录制一旦开始,我们会发现应用启动起来了,然后就可以在应用上进行常规的操作了。例如,我们可以在文

本框中输入5000,然后点击“计算”按钮,计算获得的结果45.00会显示到标签上。这些操作都被UI Recording记

录下来,并且在测试用例类中生成了代码,如图22-8所示,我们也可以点击“停止”按钮 停止录制。

图22-8 停止录制脚本

Page 19: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

22.4 访问 UI 元素 595

22.3.3 修改录制脚本

UI Recording工具将我们的操作录制下来,录制的脚本不会有if和for等逻辑分支和循环语句,录制脚本只是

针对特定控件的。例如,我们要想删除表视图中所有的单元格,但是录制过程中只是删除了其中一个单元格,此

时需要修改脚本,为其添加for和if等语句,使之适用于所有的单元格。

另外,录制的脚本也不会生成断言。需要什么断言,一般是在设计测试用例时确定下来的。在本例中,我们

需要断言计算结果标签是45.00。修改代码如下:

func testExample() {

/////////////录制生成的脚本开始///////////////////

let app = XCUIApplication()

let textfieldRevenueTextField = app.textFields["TextField Revenue"]

textfieldRevenueTextField.tap()

textfieldRevenueTextField.typeText("5000")

app.buttons["Calculate Button"].tap()

/////////////录制生成的脚本结束//////////////////

//自己添加的代码

let lbl = app.staticTexts["45.00"] ①

XCTAssert(lbl.exists) ②

}

- (void)testExample {

/////////////录制生成的脚本开始///////////////////

XCUIApplication *app = [[XCUIApplication alloc] init];

XCUIElement *textfieldRevenueTextField = app.textFields[@"TextField

Revenue"];

[textfieldRevenueTextField tap];

[textfieldRevenueTextField typeText:@"5000"];

[app.buttons[@"Calculate Button"] tap];

/////////////录制生成的脚本结束//////////////////

//自己添加的代码

XCUIElement* lbl = app.staticTexts[@"45.00"]; ①

XCTAssert(lbl.exists); ②

}

上述代码中第①行~第②行是自己添加的代码,第①行的app对象是XCUIApplication实例。关于XCUIApplication

类,我们将在下一节中详细介绍,app.staticTexts["45.00"](Objective-C版app.staticTests[@"45.00"])是获得

45.00静态文本元素对象,如果计算的结果不是45.00,那么lbl对象会不存在。第②行用于断言lbl对象是否存在,

其中exists属性是布尔值。

XCTAssert断言函数是在XCTest中提供的。在UI测试时,可以使用XCTest框架中的所有断言函数。至

于运行测试用例,可参考第21章,这里不再赘述。

22.4 访问 UI 元素

在测试过程中需要访问UI元素,而这些UI元素的API是从UIAutomation API传承下来的,本节就简要介绍一

下它们。

22.4.1 UI 元素层次结构树

在介绍相关的API之前,先来了解一下UI元素层次树。我们在介绍前面介绍iOS界面构建时,提到过界面是

由视图按照层次结构构建起来的,UI测试框架也采用类似的层次结构管理UI元素。

图22-9是第6章介绍的简单表视图的SimpleTable案例。

Page 20: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

596 第 22 章 iOS 应用 UI 测试

图22-9 SimpleTable案例

界面中的UI元素构成如下所示的层次结构树:

Application

|____Window

|____Table

|__Cell

| |____ StaticText , label: 'A1-南非'

|

|__Cell

| |____StaticText , label: 'A2-墨西哥'

|

|__Cell

| |____StaticText , label: 'B1-阿根廷'

|

|__Cell

| |____StaticText , label: 'B2-尼日利亚'

|

|__Cell

| |____StaticText , label: 'C1-英格兰'

|

|__Cell

| |____StaticText , label: 'C2-美国'

|

|__Cell

| |____StaticText , label: 'D1-德国'

|

|__Cell

| |____StaticText , label: 'D2-澳大利亚'

|

|__Cell

| |____StaticText , label: 'E1-荷兰'

|

|__Cell

| |____StaticText , label: 'E2-丹麦'

|

|__Cell

| |____StaticText , label: 'G1-巴西'

|

Page 21: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

22.4 访问 UI 元素 597

|__Cell

| |____StaticText , label: 'G2-朝鲜'

|

|__Cell

| |____StaticText , label: 'H1-西班牙'

|

|__Cell

|____StaticText , label: 'H2-瑞士'

Application是根元素,其他元素都是它的后代(descendant)元素,Window是Application的直接子(child)

元素,Table是Application的直接子元素,Table当然也是Application的后代元素。以此类推,Cell是Table的直

接子元素,StaticText是Cell的直接子元素。

Application、Window、Table、Cell和StaticText是构成界面的UI元素类型。在UI测试框架中,定义了81种元

素类型,有一些是iOS特有的,有些是OS X特有的,这里我们重点介绍几个iOS中常用的元素类型,如表22-1所示。

表22-1 iOS常用元素类型

元素类型 说 明 Application 应用程序类型

Window Window类型

Table 表视图类型

Cell 表视图中的单元格类型

StaticText 静态文本类型,如标签等视图

TextField 文本框类型

SecureTextField 密码框类型

Button 按钮类型

Slider 滑块类型

Switch 开关类型

22.4.2 UI 测试中相关 API

在iOS 9之后,XCTest框架中增加了与UI测试相关的API,其中主要的类有XCUIElement、XCUIApplication和

XCUIElementQuery。XCUIElement表示被测试应用中的元素,其主要方法和属性如下。

exists属性。判断元素是否存在。

– descendantsMatchingType:方法。指定类型查找层次结构中的所有后代元素,返回值是XCUIElementQuery

类型。

– childrenMatchingType:方法。指定类型查找层次结构中的所有直接子元素,返回值是XCUIElementQuery

类型。

– typeText:方法。获得焦点后,模拟键盘输入字符到元素。

– tap方法。点击元素动作。

– doubleTap方法。双击元素动作。

XCUIApplication是XCUIElement的子类,表示被测试的应用,主要方法只有下面这个。

– launch方法。启动被测试的应用程序。

XCUIElementQuery类用来查询XCUIElement元素,它事实上是集合类型。查询单个元素相关的方法如下。

– elementBoundByIndex:。通过索引访问元素。

– elementMatchingPredicate:。通过谓词NSPredicate指定查询条件进行查询。

– elementMatchingType:identifier:。指定类型,通过id进行查询。

– objectForKeyedSubscript:。通过下标访问元素,它的简化形式为[],例如app.textFields["TextField

Page 22: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

598 第 22 章 iOS 应用 UI 测试

Revenue"](Objective-C版本为app.textFields[@"TextField Revenue"])。

XCUIElementQuery中查询多个元素相关的方法如下。

– descendantsMatchingType:。指定类型查找层次结构中的所有后代元素。

– childrenMatchingType:。指定类型查找层次结构中的所有直接子元素。

– matchingPredicate:。通过谓词NSPredicate指定查询条件进行查询。

– matchingType:identifier:。指定类型,通过id进行查询。

– matchingIdentifier:。通过id进行查询。

– containingPredicate:。在后代元素中,通过谓词NSPredicate指定查询条件进行查询。

– containingType:identifier:。在后代元素中,通过指定类型,通过id进行查询。

XCUIElementQuery中的属性如下。

element。获取单个XCUIElement元素。

count。获取元素的个数。

debugDescription。调试信息。

22.5 表示层测试最佳实践

我们在21.5节中介绍了MyNotes案例的业务逻辑层和数据持久层测试,这一节就来实现MyNotes案例的表示

层测试。由于有着良好的分层设计,表示层中已经没有业务逻辑代码了,表示层变得非常轻薄,所以表示层测试

的重点就是UI测试了。

首先,参考22.2.2节为表示层工程PresentationLayer添加UI测试用例目标。注意,根据表示层采用的语言,选

择测试用例语言。

22.5.1 配置 UI 测试用例目标

如果此时运行测试用例目标,则会出现如图22-10所示的运行错误。错误信息如下:

dyld: Library not loaded: @rpath/BusinessLogicLayer.framework/BusinessLogicLayer

Referenced from: /Users/tony/Library/Developer/CoreSimulator/Devices/206F9D01-DA54-4957-AF88-311003F9D629/data/Containers/Bundle/Application

/D53EE69F-5A60-4331-B9B3-0378EB10B625/PresentationLayer.app/PresentationLayer

Reason: image not found

图22-10 运行错误

Page 23: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

22.5 表示层测试最佳实践 599

dyld: Library not loaded这个错误我们在11.6.3节遇到过,当时的情况是在设备上运行时,需要将

表示层所依赖的框架BusinessLogicLayer.framework和PersistenceLayer.framework设置为嵌入方式。

而这里之所以出现dyld: Library not loaded错误,是因为UI测试目标运行时,通过XCTRunner工具运行被

测试程序,XCTRunner要求BusinessLogicLayer.framework和PersistenceLayer.framework等第三方框架以嵌入方式

设置。

要在应用程序目标中嵌入框架,可以按照图22-11,选择TARGETS→PresentationLayer→General→Embedded

Binaries。选择左下角的+按钮,然后从弹出界面中选择BusinessLogicLayer.framework和PersistenceLayer.framework,

再点击Add按钮即可。

图22-11 在应用目标中嵌入框架

在应用程序目标中嵌入第三方框架后,最好在设备下运行测试用例,如果只能在模拟器下运行测试

用例,那么你的代码的组织形式不要采用WF(基于自定义框架实现的同一个工作空间不同工程的分

层)模式,而最好是TF(基于自定义框架实现的同一个工程不同目标的分层)模式,具体如表22-2

所述。

表22-2 嵌入框架代码组织形式与运行环境

代码组织形式 模 拟 器 设 备 WF 不能运行测试用例 可以运行测试用例

TF 能运行测试用例 能运行测试用例

此外,为了便于访问界面中的UI元素,需要设置UI元素的辅助功能相关属性。本例中,我们主要是为“增加”

界面的TextView控件设置标签属性Text View,具体步骤可参考22.3.1节。

22.5.2 编写 UI 测试用例

表示层中的UI测试用例设计是与界面操作有关的,我们总结了如下界面操作。

Page 24: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

600 第 22 章 iOS 应用 UI 测试

备忘录查询操作。

增加备忘录操作。

删除备忘录操作。

显示备忘录详细信息操作。

1.备忘录查询操作 备忘录查询操作就是首页显示时,从业务逻辑层获得数据显示到表视图单元格中。我们需要断言表视图单元

格的行数,以及每一个单元格内容与数据库中对应的字段是否一致。

测试用例PresentationLayerUITests中相关测试代码如下:

//PresentationLayerUITests.swift文件

//MARK: -- 查询操作

func testMasterViewControllerTableViewCellFindAll() {

let app = XCUIApplication()

//获得当前界面中的表视图

let tableView = app.tables.elementBoundByIndex(0) ①

//断言表视图存在

XCTAssert(tableView.exists)

//断言表视图单元格数为0

XCTAssertEqual(tableView.cells.count, 2)

let cell1 = tableView.cells.elementBoundByIndex(0) ②

XCTAssert(cell1.staticTexts["Welcome"].exists) ③

let cell2 = tableView.cells.elementBoundByIndex(1)

XCTAssert(cell2.staticTexts["欢迎"].exists)

}

//PresentationLayerUITests.m文件

#pragma mark -- 查询操作

- (void)testMasterViewControllerTableViewCellFindAll {

XCUIApplication* app = [[XCUIApplication alloc] init];

//获得当前界面中的表视图

XCUIElement* tableView = [app.tables elementBoundByIndex:0]; ①

//断言表视图存在

XCTAssert(tableView.exists);

//断言表视图单元格数为0

XCTAssertEqual(tableView.cells.count, 2);

XCUIElement* cell1 = [tableView.cells elementBoundByIndex:0]; ②

XCTAssert(cell1.staticTexts[@"Welcome"].exists); ③

XCUIElement* cell2 = [tableView.cells elementBoundByIndex:1];

XCTAssert(cell2.staticTexts[@"欢迎"].exists);

}

上述代码中第①行用于获得当前界面中的第一个表视图,其中app.tables用于获得当前界面中所有的表视图。

app.tables这个写法事实上是app.descendantsMatchingType(.Table) (Objective-C是[app descendantsMatchingType:

XCUIElementTypeTable])简化写法,即查找app中所有的后代元素。

第②行代码用于获得表视图中的第一个单元格元素,其中表达式tableView.cells是tableView.descendants-

Matching Type(.Cell)(Objective-C是[tableView descendantsMatchingType:XCUIElementTypeCell])的简化写法。

第 ③ 行 代 码 用 于 断 言 第 一 个 单 元 格 中 文 本 内 容 是 否 为 Welcome , 其 中 表 达 式 cell1.staticTexts 是

cell1.descendantsMatchingType(.StaticText) (Objective-C是[cell1 descendantsMatchingType:XCUIElementTypeStatic

Text])的简化写法。表达式staticTexts["Welcome"](Objective-C是staticTexts[@"Welcome"])是通过下标访问元素,

是–objectForKeyedSubscript:方法的简化形式。

上述测试用例方法运行之前,应该先启动应用修改数据,要保证只有两条数据,内容是:Welcome

和“欢迎”,并且保证第一个单元格的内容是Welcome,第二个单元格的内容是“欢迎”。

2.增加备忘录操作 增加备忘录操作的过程是,用户点击首页中的Add按钮,界面跳转到增加界面,在TextView中输入内容,点

击Save按钮回到首页。我们需要断言表视图中是否增加了一个单元格。如果在增加界面中点击Cancel按钮,可以

取消操作,返回首页。

测试用例PresentationLayerUITests中相关测试代码如下:

//MARK:-- 增加备忘录操作

func testAddViewControllerSave() {

#pragma mark -- 增加备忘录操作

- (void)testAddViewControllerSave {

Page 25: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

22.5 表示层测试最佳实践 601

let app = XCUIApplication()

//获得当前界面中的表视图

let tableView = app.tables.elementBoundByIndex(0)

let cellsCount = tableView.cells.count

//点击“增加”按钮,跳转到增加界面

app.navigationBars["备忘录"].buttons["Add"].tap() ①

//获得增加界面中的TextView对象

let textView = app.textViews["Text View"]

textView.tap()

textView.typeText("HelloWorld") ②

//在增加界面中添加Save按钮,跳转到备忘录界面

app.navigationBars["增加"].buttons["Save"].tap()

//断言备忘录界面中表视图单元格数为+1 XCTAssertEqual(tableView.cells.count, cellsCount + 1)

}

//MARK: -- 增加备忘录时取消操作

func testAddViewControllerCancel() {

let app = XCUIApplication()

//获得当前界面中的表视图

let tableView = app.tables.elementBoundByIndex(0)

let cellsCount = tableView.cells.count

//点击“增加”按钮,跳转到增加界面

app.navigationBars["备忘录"].buttons["Add"].tap()

//在增加界面中添加Save按钮,跳转到备忘录界面

app.navigationBars["增加"].buttons["Cancel"].tap()

//断言备忘录界面中表视图单元格数没有+1 XCTAssertEqual(tableView.cells.count, cellsCount)

}

XCUIApplication* app = [[XCUIApplication alloc] init];

//获得当前界面中的表视图

XCUIElement* tableView = [app.tables elementBoundByIndex:0];

NSUInteger cellsCount = tableView.cells.count;

//点击“增加”按钮,跳转到增加界面

[app.navigationBars[@"备忘录"].buttons[@"Add"] tap]; ①

//获得增加界面中的TextView对象

XCUIElement* textView = app.textViews[@"Text View"];

[textView tap];

[textView typeText:@"HelloWorld"]; ②

//在增加界面中添加Save按钮,跳转到备忘录界面

[app.navigationBars[@"增加"].buttons[@"Save"] tap];

//断言备忘录界面中表视图单元格数为+1 XCTAssertEqual(tableView.cells.count, cellsCount + 1);

}

#pragma mark -- 增加备忘录时取消操作

- (void)testAddViewControllerCancel {

XCUIApplication* app = [[XCUIApplication alloc] init];

//获得当前界面中的表视图

XCUIElement* tableView = [app.tables elementBoundByIndex:0];

NSUInteger cellsCount = tableView.cells.count;

//点击“增加”按钮,跳转到增加界面

[app.navigationBars[@"备忘录"].buttons[@"Add"] tap];

//在增加界面中添加Save按钮,跳转到备忘录界面

[app.navigationBars[@"增加"].buttons[@"Cancel"] tap];

//断言备忘录界面中表视图单元格数没有+1 XCTAssertEqual(tableView.cells.count, cellsCount);

}

上述代码中,第①行是点击Add按钮,结果会跳转到增加界面。第②行是通过键盘在textView中输入字符串。

3. 删除备忘录操作 删除备忘录操作的过程是,用户点击首页中的Edit按钮,使表视图处于编辑状态,然后点击单元格删除按钮

,再点击单元格后面的删除确定按钮 ,删除之后再点击Done完成操作。删除成功后我们会断言,单元格是

否减少了一行,还要断言删除的单元格数据已经不存在了。

测试用例PresentationLayerUITests中相关测试代码如下: //MARK: -- 删除最后一个单元格的操作

func testMasterViewControllerTableViewCellRemove() {

let app = XCUIApplication()

let navigationBar = app.navigationBars["备忘录"]

navigationBar.buttons["Edit"].tap()

let tableView = app.tables.elementBoundByIndex(0)

let cellsCount = tableView.cells.count

tableView.buttons.elementBoundByIndex(1).tap()

tableView.buttons["Delete"].tap()

navigationBar.buttons["Done"].tap()

XCTAssertEqual(tableView.cells.count, cellsCount - 1)

let staticTexts = tableView.cells.staticTexts["Welcome"] ① //tableView.staticTexts["Welcome"] ②

XCTAssert(!staticTexts.exists) ③

}

#pragma mark -- 删除最后一个单元格的操作

- (void)testMasterViewControllerTableViewCellRemove {

XCUIApplication* app = [[XCUIApplication alloc] init];

XCUIElement* navigationBar = app.navigationBars[@"备忘录"];

[navigationBar.buttons[@"Edit"] tap];

XCUIElement* tableView = [app.tables elementBoundByIndex:0];

NSUInteger cellsCount = tableView.cells.count;

[[tableView.buttons elementBoundByIndex:0] tap];

[tableView.buttons[@"Delete"] tap];

[navigationBar.buttons[@"Done"] tap];

XCTAssertEqual(tableView.cells.count, cellsCount - 1);

XCUIElement* staticTexts = tableView.cells.staticTexts[@"Welcome"]; ① //tableView.staticTexts[@"Welcome"]; ②

XCTAssert(!staticTexts.exists); ③

}

Page 26: 内 容 提 要 - 51CTOs3.51cto.com/wyfs02/M01/84/6C/wKioL1eQb8ehZcABACsU9jRtYHQ… · 第17 章介绍了Web Service,并重点讨论了REST 风格Web Service,其中具体访问Web

602 第 22 章 iOS 应用 UI 测试

第①行代码用于试图获得删除单元格中的静态文本,第③行代码用于断言这个对象不存在。需要注意的是,

第①行也可以使用第②行语句替换,这是因为它们都是descendantsMatchingType:的简化写法,即从后代元素中

查找,单元格中的静态文本元素是单元格的子元素,更是表视图的子元素。

上述测试用例方法运行之前,我们应该先启动应用修改数据,要保证第一个单元格的内容是

Welcome。

4. 显示备忘录详细信息操作 显示备忘录详细信息的操作是,用户点击首页中的某个单元格,界面跳转到详细界面,我们需要断言详细界

面TextView中的内容是否等于选中单元格中的文本。然后,点击左上角的返回按钮回到首页。

测试用例PresentationLayerUITests中相关测试代码如下:

//MARK: -- 显示详细信息操作

func testDetailViewControllerShowDetail() {

let app = XCUIApplication()

//获得当前界面中的表视图

let tableView = app.tables.elementBoundByIndex(0)

let cell1 = tableView.cells.elementBoundByIndex(0)

cell1.tap()

let welcomeStaticText = app.staticTexts["Welcome"]

//断言

XCTAssert(welcomeStaticText.exists)

app.navigationBars["详细"].buttons["备忘录"].tap()

}

#pragma mark –– 显示详细信息操作

- (void)testDetailViewControllerShowDetail {

XCUIApplication* app = [[XCUIApplication alloc] init];

//获得当前界面中的表视图

XCUIElement* tableView = [app.tables elementBoundByIndex:0];

XCUIElement* cell1 = [tableView.cells elementBoundByIndex:0];

[cell1 tap];

XCUIElement* welcomeStaticText = app.staticTexts[@"Welcome"];

//断言

XCTAssert(welcomeStaticText.exists);

[app.navigationBars[@"详细"].buttons[@"备忘录"] tap];

}

上述测试用例方法运行之前,我们应该先启动应用修改数据,保证点击的单元格内容是Welcome。

22.6 小结

通过本章的学习,我们了解了iOS 9中的UI测试框架,它基于XCTest和UIAutomation框架。 后,我们还介

绍了如何在分层架构中实施UI测试。