iOS软件开发揭密:iPhone&iPad企业应用和游戏开发


内 容 简 介 本书以严密的体系性提供了 iPhone 和 iPad 软件开发从入门到专家的系统性知识,并提供来源于真实项 目的可重用商业代码。书中的每个实例都是项目经验的提炼,深入浅出地讲解 iPhone 和 iPad 软件开发的核 心技术要点,基本涵盖了 iOS 软件开发在真实商业项目中所需要的所有主题,并将实例介绍的技术深度和超 值的实用性结合在一起,成为本书的特色。 随书附赠的光盘中包含了书中大量案例的完整工程源代码,可以让读者参考学习。 本书既可以作为大学教材、企业培训教材,亦可作为苹果技术专业参考书籍,适合大学师生、企业管理 人员、开发人员、培训机构教师和学员、IT 业界人士等参考和阅读。 未经许可,不得以任何方式复制或抄袭本书之部分或全部内容。 版权所有,侵权必究。 图书在版编目(CIP)数据 iOS 软件开发揭密:iPhone&iPad 企业应用和游戏开发 / 虞斌著. —北京:电子工业出版社,2011.5 ISBN 978-7-121-13302-2 Ⅰ. ①i… Ⅱ. ①虞… Ⅲ. ①面向对象语言-程序设计 Ⅳ. ①TP312 中国版本图书馆 CIP 数据核字(2011)第 064333 号 策划编辑:林瑞和 责任编辑:徐津平 文字编辑:张丹阳 印 刷:北京天宇星印刷厂 装 订:三河市皇庄路通装订厂 出版发行:电子工业出版社 北京市海淀区万寿路 173 信箱 邮编 100036 开 本:787×980 1/16 印张:27.5 字数:532 千字 印 次:2011 年 5 月第 1 次印刷 印 数:5000 册 定价:79.00 元(含 DVD 光盘 1 张) 凡所购买电子工业出版社图书有缺损问题,请向购买书店调换。若书店售缺,请与本社发行部联系,联 系及邮购电话:(010)88254888。 质量投诉请发邮件至 zlts@phei.com.cn,盗版侵权举报请发邮件至 dbqq@phei.com.cn。 服务热线:(010)88258888。 序┃ “Even if I knew that tomorrow the world would go to pieces, I would still plant my apple tree.” “即使我知道明天的世界会垮掉,我还是会种下我的苹果树。” ——马丁·路德 苹果公司(NASDAQ:AAPL,以前名为苹果电脑公司)是一家历史悠久的美 国跨国公司,设计和销售消费电子产品、计算机软件和个人电脑。苹果公司于 1976 年 4 月 1 日在加州 Upertino 成立,早期主要销售 Macintosh 系列个人电脑和各种相关软件,2007 年 1 月 9 日,苹果公司发布了具有里程碑意义的 iPhone 手机,彻底改变了移动电话业务。 从运营商手中夺取权力,交给制造商、开发商和消费者,iPhone 完全改变了运营商和制造 商的行为,其崭新的商业模式改变了移动业务的游戏规则,截至 2008 年 6 月,App Store 汇集了 30 万个苹果批准的“应用程序”,App Store 赋予了缺少市场运作能力的第三方开 发商和草根开发者新的商业机会,让开发商和个体开发者编写软件,而市场和销售则交给 苹果公司管理。在 App Store 商业模式的推动下,iPhone 以其创新的产品特性获得了巨大 的市场成功,随着个人消费电子市场的不断扩展,苹果公司于 2010 年 4 月又发布了具有 各种创新特性的 iPad 个人平板电脑,在 iPad 发布后的 80 天内即销售了 3 万台设备,iPad、 iPhone、iPod Touch 使用相同的操作系统 iOS,这给开发者带来极大的便利。其实,苹果 公司早在 1993 年就开始了 iPad 平板电脑的研发,直到 2010 年才最终将其推出市场,iPad ┃iOS 软件开发揭密:iPhone&iPad 企业应用和游戏开发┃ IV 的推出也宣告了个人平板电脑时代的到来,人们将以崭新的方式来使用互联网、操作电脑 游戏和阅读电子图书。 苹果公司在全球范围内始终具有独特的影响力,是 IT 界最重要的品牌之一,特别是 随着 iPhone 和 iPad 的发布,苹果公司在个人消费电子市场更是具有执掌牛耳的影响力。 无论是对苹果公司的赞誉还是批评,研究、借鉴苹果公司产品的综合审美设计、独特的广 告活动、市场销售和商业模式以及公司经营理念都是 IT 界不可忽视的重要课题,在进行 产品设计、广告宣传、软件研发等各方面都具有重要的借鉴意义。 本书既可以作为培训教材,也可 以 作为苹果软件商业项目开发实战参考用书,让想要 了解苹果技术的大学、企业、培训机构和个人对苹果技术有一个系统的认识,并掌握 iPhone 和 iPad 软件开发涉及的主要核心技术,在进行 iOS 相关企业应用软件和游戏的开发时具 备相应的技术基础、核心知识和参考实例。 前 言┃ 随着 iPhone 和 iPad 在中国的上市,国内 iPhone、iPad 用户急剧增加,加剧了 iPhone 软件市场的增长,学习和掌握苹果开发技术已经成为企业、大学计算机学院、软件学院不 可或缺的一个重要方向。学习和掌握苹果 iOS 软件开发技术是大势所趋,国内有的大学已 经将 iOS 软件开发作为新开课程方向,市面上做 iOS 软件开发培训的公司都是获取高额利 润的公司,学员收费竟高达五位数以上,有经验的开发者花一天时间做一个非常小的 iPhone 或者 iPad 软件就可以轻松赚取几百到几千美元。 本书的目的是让初学者能够系统地学习 iPhone 开发的基础知识,让你在学习 iPhone 软件开发的过程中少走弯路,掌握技术精要,使你能够快速步入 iPhone 开发的殿堂,同 时也为有经验的开发者提供实用的编程技巧、思路和参考实例。这些宝贵的实例是在进行 iPhone 开发时需要的第一手素材,是你在实际开发 iPhone 软件遇到问题时最珍贵的资源, 有效使用这些资源能让你快速解决问题,实现软件需要的功能,节约宝贵的时间。本书系 统地介绍了 iPhone 和 iPad 软件开发的基础知识、技术精要、实用的编程技巧、思路和参 考实例,涵 盖了 iOS 软件开发的各种核心技术,包括企业应用和游戏开发。书中的每个实 例、每个技术要点都来自真实的商业项目,这些精选的主题是进行 iOS 软件开发时必须掌 握的核心内容。 本书的内容是来自实践的核心技术讲解,不同于玩具代码或者普通的教学代码,玩具 代码或者普通的教学代码不能让读者真正完成真实商业项目的开发。 本书既可以作为大学教材、企业培训教材,亦可作为苹果技术专业参考书籍,适合大 学师生、企业管理人员、开发人员、培训机构教师和学员、IT 业界人士等参考和阅读。 本书的出版得到了电子工业出版社的大力支持,在此感谢电子工业出版社编辑林瑞 和、张丹阳为本书出版所做的大量工作,感谢美术编辑李玲为本书设计的精美封面,同时 ┃iOS 软件开发揭密:iPhone&iPad 企业应用和游戏开发┃ VI 也感谢其他所有参与本书出版工作的朋友们。 目 录┃ 第 1 章 iPhone开发环境设置 ............................................................................................... 1 1.1 安装雪豹操作系统 .............................................................................................. 2 1.2 安装iPhone SDK .................................................................................................. 5 1.3 无证书开发环境Xcode设置 ............................................................................... 7 1.4 有证书开发环境Xcode设置 ............................................................................. 11 1.5 安装源代码版本管理工具 ................................................................................ 12 1.6 安装Wine ........................................................................................................... 12 1.7 使用Wine安装Source Insight ............................................................................ 13 1.8 相关网络资源 .................................................................................................... 14 第 2 章 Objective-C编程基础 ............................................................................................ 15 2.1 Objective-C介绍 ................................................................................................ 16 2.2 第一个iPhone程序 ............................................................................................. 16 2.3 Objective-C基本类型 ........................................................................................ 17 2.3.1 id ............................................................................................................... 17 2.3.2 SEL ........................................................................................................... 17 2.3.3 BOOL ........................................................................................................ 18 2.3.4 nil、NULL和NSNull ................................................................................... 18 2.4 常量声明和预处理宏 ........................................................................................ 20 2.5 使用#import包含头文件 ................................................................................... 22 2.6 使用#pragma mark分隔代码块 ......................................................................... 22 2.7 Objective-C内存管理:retain和release ............................................................ 22 ┃iOS 软件开发揭密:iPhone&iPad 企业应用和游戏开发┃ VIII 2.8 字符串操作........................................................................................................ 26 2.8.1 字符串常量 ................................................................................................ 26 2.8.2 获取子字符串 ............................................................................................. 27 2.8.3 合并和格式化字符串 ................................................................................... 28 2.8.4 分隔字符串 ................................................................................................ 28 2.8.5 NSString和char*之间的转换 ......................................................................... 29 2.8.6 字符串比较 ................................................................................................ 29 2.9 处理数值对象.................................................................................................... 30 2.10 处理日期时间NSDate ..................................................................................... 31 2.11 处理NSData类型 ............................................................................................. 32 2.12 集合操作 ......................................................................................................... 32 2.12.1 数组操作:NSArray和NSMutableArray ....................................................... 32 2.12.2 字典操作:NSDictionary和NSMutableDictionary .......................................... 42 2.12.3 集合操作:NSSet和NSMutableSet .............................................................. 47 2.12.4 堆栈操作 .................................................................................................. 49 2.13 面向对象编程:类、实例和消息 .................................................................. 50 2.13.1 类定义 ..................................................................................................... 50 2.13.2 类构造和构析函数 .................................................................................... 51 2.13.3 Singleton模式 ............................................................................................ 53 2.13.4 @class、@protocol前向声明 ...................................................................... 53 2.13.5 self和super ................................................................................................ 54 2.13.6 实例方法和类方法 .................................................................................... 54 2.13.7 对象属性(@property) ............................................................................ 55 2.13.8 静态属性(static attributes) ...................................................................... 58 2.14 类扩展(Class Categories) ........................................................................... 59 2.15 Objective-C接口编程 ...................................................................................... 60 2.15.1 接口编程之@protocol ................................................................................ 60 2.15.2 接口编程之后台线程 ................................................................................. 63 2.15.3 接口编程之Notifications ............................................................................. 65 2.15.4 接口编程之NSOperationQueue .................................................................... 68 2.15.5 接口编程之私有方法 ................................................................................. 69 ┃目 录┃ IX 2.15.6 接口编程之静态库隐藏类 .......................................................................... 70 2.15.7 接口编程之@protocol封装类 ...................................................................... 72 2.15.8 接口稳定性和接口继承 .............................................................................. 73 2.16 定时器(NSTimer)编程 ............................................................................... 77 2.17 序列化和反序列化 .......................................................................................... 78 2.17.1 序列化方法之Property List ......................................................................... 78 2.17.2 序列化方法之NSKeyedArchiver .................................................................. 78 2.17.3 序列化方法之Core Data ............................................................................. 79 2.18 Objective-C和C、C++混合编程 .................................................................... 80 2.19 消息和NSInvocation........................................................................................ 87 2.20 方法混合(Method Swizzling) .................................................................... 90 2.21 使用NSAssert进行代码调试 .......................................................................... 93 2.22 本章总结 .......................................................................................................... 93 2.23 参考书籍 .......................................................................................................... 93 第 3 章 iPhone SDK开发基础............................................................................................ 95 3.1 iPhone SDK介绍 ................................................................................................ 96 3.2 第一个iPhone 界面程序 ................................................................................... 99 3.3 iPhone程序启动过程 ....................................................................................... 105 3.4 iPhone程序生命周期 ....................................................................................... 107 3.5 掌握iPhone程序通信中心UIApplication和UIApplicationDelegate ............... 110 3.6 iPhone坐标系统 ............................................................................................... 111 3.7 UIView层次管理 ............................................................................................. 116 3.8 触控(Touch)测试 ........................................................................................ 120 3.9 多点触控(MultiTouch)和物体移动 ........................................................... 122 3.10 UIView旋转和缩放 ....................................................................................... 125 3.11 UIScrollView编程 .......................................................................................... 127 3.12 iPhone程序框架 ............................................................................................. 129 3.12.1 使用UINavigationController组织和管理UIView .......................................... 130 3.12.2 使用UITabBarController组织和管理UIView ............................................... 130 3.12.3 使用UISplitViewController组织和管理UIView ............................................ 133 ┃iOS 软件开发揭密:iPhone&iPad 企业应用和游戏开发┃ X 3.13 旋转屏幕(Screen Rotations) .................................................................... 135 3.14 掌握UIButton编程 ........................................................................................ 138 3.15 管理界面字体................................................................................................ 139 3.16 使用UILabel管理界面文本 .......................................................................... 141 3.17 管理界面颜色................................................................................................ 143 3.18 界面风格(TRANSITIONING STYLES) ................................................. 148 3.19 单词排序表格编程 ........................................................................................ 149 3.20 NSUserDefaults和Property List文件............................................................. 150 3.21 文件系统和外部资源管理 ............................................................................ 152 3.22 简单动画制作................................................................................................ 155 3.23 闪屏制作——程序启动动画 ........................................................................ 157 3.24 多行文本输入控件制作 ................................................................................ 159 3.25 图片处理 ....................................................................................................... 162 3.26 Core Audio编程 ............................................................................................. 163 3.27 UITableView编程 .......................................................................................... 165 3.28 UISegmentedControl编程 ............................................................................. 167 3.29 OpenFlow编程 ............................................................................................... 169 3.30 UIPageControl编程 ....................................................................................... 172 3.31 自定义仪表控件 ............................................................................................ 175 3.32 本章总结 ....................................................................................................... 180 第 4 章 iPhone SDK高级编程 ......................................................................................... 181 4.1 Base64 编解码 ................................................................................................. 182 4.2 Web Service和XML数据解析......................................................................... 183 4.3 JSON数据解析 ................................................................................................ 184 4.4 掌握SQLite管理用户数据 .............................................................................. 187 4.5 缓存(Caching)及Core Data数据管理 ........................................................ 191 4.6 使用AES算法进行数据加解密 ...................................................................... 207 4.7 电子商务安全基础——RSA算法和数据加密 .............................................. 210 4.7.1 开发.NET版本RSA算法库 ......................................................................... 210 4.7.2 建立iPhone版本RSA算法库 ....................................................................... 217 ┃目 录┃ XI 4.8 自定义用户界面控件制作 .............................................................................. 220 4.8.1 ComboBox控件和UIPikerView设计 ............................................................. 220 4.8.2 自定义UIDatePicker制作 ............................................................................ 224 4.9 UIWebView和JavaScript高级编程 ................................................................. 229 4.10 本章总结 ........................................................................................................ 236 第 5 章 iPhone企业应用实例分析 ................................................................................... 237 5.1 综合应用概述 .................................................................................................. 238 5.2 系统介绍 .......................................................................................................... 238 5.3 系统需求和主要用例 ...................................................................................... 239 5.4 程序处理流程 .................................................................................................. 241 5.5 主要实现类和相互关系 .................................................................................. 242 5.6 程序框架分析 .................................................................................................. 244 5.7 技术要点分析 .................................................................................................. 249 5.7.1 异步网络通信 ........................................................................................... 249 5.7.2 Core Data缓存数据 .................................................................................... 252 5.7.3 RSA算法加解密 ........................................................................................ 258 5.7.4 自定义控件制作........................................................................................ 258 5.7.5 表格控件定制 ........................................................................................... 260 5.7.6 自定义UIToolbar ....................................................................................... 266 5.7.7 目录浏览器制作........................................................................................ 268 5.7.8 文件上传和下载........................................................................................ 273 5.8 本章总结 .......................................................................................................... 277 第 6 章 iPad软件开发基础................................................................................................ 279 6.1 iPad软件开发介绍 ........................................................................................... 280 6.2 UISplitViewController编程 ............................................................................. 280 6.3 UIPopoverController编程 ................................................................................ 287 6.4 定制MPMoviePlayerController进行视频播放 ............................................... 290 6.5 开发调色板(Palette)控件 ........................................................................... 294 6.6 发送邮件 .......................................................................................................... 296 6.7 Google地图编程 .............................................................................................. 297 ┃iOS 软件开发揭密:iPhone&iPad 企业应用和游戏开发┃ XII 6.8 本章总结 ......................................................................................................... 314 第 7 章 iPad商业软件实例分析 ....................................................................................... 317 7.1 综合应用概述.................................................................................................. 318 7.2 系统介绍 ......................................................................................................... 318 7.3 系统需求和主要用例 ...................................................................................... 319 7.4 程序处理流程.................................................................................................. 321 7.5 主要实现类和相互关系 .................................................................................. 321 7.6 程序框架 ......................................................................................................... 323 7.7 技术要点分析.................................................................................................. 335 7.7.1 图片分页和滚动显示 ................................................................................. 335 7.7.2 动态管理多国语言界面 ............................................................................. 340 7.7.3 播放网络视频 ........................................................................................... 341 7.8 本章总结 ......................................................................................................... 344 第 8 章 iOS游戏开发基础 ................................................................................................. 345 8.1 概述 ................................................................................................................. 346 8.2 cocos2d系统介绍 ............................................................................................ 346 8.3 cocos2d编程基础 ............................................................................................ 349 8.3.1 第一个cocos2d程序 ................................................................................... 349 8.3.2 基本动画 .................................................................................................. 353 8.4 Box2D物理引擎 .............................................................................................. 356 8.4.1 核心概念 .................................................................................................. 356 8.4.2 碰撞检测 .................................................................................................. 357 8.5 Chipmuck物理引擎 ......................................................................................... 361 8.5.1 重要概念 .................................................................................................. 361 8.5.2 物理模拟和碰撞检测 ................................................................................. 363 8.6 粒子系统 ......................................................................................................... 365 8.6.1 轨道卫星(Orbit Satellite) ........................................................................ 366 8.6.2 太空陨石(Space Rocks) ......................................................................... 367 8.7 本章总结 ......................................................................................................... 369 ┃目 录┃ XIII 第 9 章 iOS商业游戏实例分析 ......................................................................................... 371 9.1 概述 .................................................................................................................. 372 9.2 闪回(Flash Back) ........................................................................................ 372 9.3 法术的释放(Ghost Castle) ......................................................................... 376 9.3.1 GhostCastle中的Tile Map管理 ..................................................................... 378 9.3.2 cocos2d中的Tile Map管理 .......................................................................... 381 9.4 甜蜜的梦(Sweet Dreams) ........................................................................... 384 9.5 毁灭之战(RavagedByWar) ......................................................................... 391 9.5.1 A*算法 .................................................................................................... 392 9.5.2 毁灭之战中的A*算法实现 ......................................................................... 397 9.6 吹吹鱼(PuffPuff) ........................................................................................ 399 9.7 本章总结 .......................................................................................................... 403 第 10 章 iPhone软件发布 ................................................................................................. 405 10.1 App Store概述 ............................................................................................... 406 10.2 iPhone软件发布步骤 ..................................................................................... 406 10.3 ipa安装包制作 ............................................................................................... 410 10.4 iOS配置文件和Settings系统编程 ................................................................. 411 10.5 本章总结 ........................................................................................................ 415 附录 ......................................................................................................................................... 417 第 3 章┃ iPhone SDK 开发基础 The heart of the discerning acquires knowledge; the ears of the wise seek it out.
 聪明人的心得知识,智慧人的耳求知识。 ——《旧约·箴言》 3.12 iPhone 程序框架 总的来说 iPhone 程序有两类框架,一类是游戏框架,另一类是非游戏框架,这里介 绍的是非游戏框架,即基于 iPhone 用户界面标准控件的程序框架。 典型的 iPhone 程序包含一个 Window 和几个 UIViewController,每个 UIViewController 管理多个 UIView(可能是 UITableView、UIWebView、UIImageView 等) , 如 图 3-24 所示。 这些 UIView 之间如何进行层次迭放、显示、隐藏、旋转、移动等都由 UIViewController 进行管理,而 UIViewController 之间的切换,通常情况是通过 UINavigationController、 UITabBarController 或 UISplitViewController 进行切换。接下来笔者会逐一介绍如何使用这 三种 Controller 来切换你的 UIViewController,以及在 UIViewController 中如何组织和管理 你的各种 UIView。 图 3-24 iPhone 程序框架示意图 ┃第 3 章 iPhone SDK 开发基础┃ 3.12.1 使用 UINavigationController 组织和管理 UIView 当你的程序具有层次化的工作流时,就比较适合使用 UINavigationController 来管理 UIViewController,即用户可以从上一层界面进入下一层界面,在下一层界面处理完以后 又可以简单地返回到上一层界面,UINavigationController 使用堆栈的方式来管理 UIViewController,进入下一层界面的代码如下。 [self.navigationController pushViewController:nextController animated:YES]; 返回上一层界面的代码如下。 [self.navigationController popViewControllerAnimated:YES]; 如图 3-25 所示,屏幕左上方的“Animal List”按钮是 返回按钮,注意这个返回按钮是 UINavigationController 自 动添加的,不需要编写任何代码在界面上添加按钮或者实 现按钮操作,当程序使用 pushViewController()函数将 ViewController 添加进 UINavigation Controller 的时候, UINavigationController 就自动显示这个返回按钮,用户单 击这个“Animal List”按钮就可以回到原先的界面, UINavigationController 的这种运行机制产生这样的效果, 用户可以一层一层地进入更深的界面层次,然后又可以一 层一层的按顺序返回,使用这样的方式来组织用户界面非 常方便。 本节相关的完整 Xcode 工程源代码文件请参考本书附 带的光盘中的 Zoo 实例。 3.12.2 使用 UITabBarController 组织和管理 UIView 当你的程序分为几个相对比较独立的部分时,就比较适合使用 UITabBarController 来 组织用户界面,如图 3-26 所示。 图 3-25 UINavigationController 程序框架实例界面 图 3-26 UITabBarController 程序框架实例界面 在屏幕的下方包含 UITabBarController 的三个按钮,用户单击不同的按钮即可以进入 不同的界面,每个界面相对来说在整个系统中比较独立,也就是程序分成了三个相对比较 独立的不同部分,在每个相对独立的部分你也可以使用 UINavigationController 等容器类组 织你的界面。这样组织使程序逻辑非常清晰,当然你也可以组织很多个 Tab 而不只是三个, 以下代码演示如何创建 UITabBarController 对象,并为其添加多个 Tab。 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions { // Override point for customization after application launch. //Create the navigation Controller UINavigationController *localNavigationController; //Create UINavigationController tabBarController = [[UITabBarController alloc] init]; tabBarController.delegate = self; // Create the array that will contain all the View controlelr NSMutableArray *localControllersArray = [[NSMutableArray alloc] init WithCapacity:3]; ┃第 3 章 iPhone SDK 开发基础┃ // Create the view controller attached to the first item in the TabBar aViewController *firstViewController; firstViewController = [aViewController alloc]; localNavigationController = [[UINavigationController alloc] initWithRoot ViewController:firstViewController]; localNavigationController.navigationBar.barStyle = UIBarStyleBlackOpaque; [localNavigationController.tabBarItem initWithTitle:@"Outlines" image:[UIImage imageNamed:@"webcast.png"] tag:1]; firstViewController.navigationItem.title = @"Outlines"; [localControllersArray addObject:localNavigationController]; [localNavigationController release]; [firstViewController release]; // Create the view controller attached to the second item in the TabBar anotherViewController *secondViewController; secondViewController = [[anotherViewController alloc] initWithStyle: UITableViewStyleGrouped ]; localNavigationController = [[UINavigationController alloc] initWithRoot ViewController:secondViewController]; [localNavigationController.tabBarItem initWithTitle:@"Q & A" image:[UIImage imageNamed:@"book.png"] tag:2]; secondViewController.navigationItem.title=@"Q & A"; [localControllersArray addObject:localNavigationController]; [localNavigationController release]; [secondViewController release]; miscViewController *thirdViewController; thirdViewController = [[miscViewController alloc] initWithStyle:UITable ViewStyleGrouped ]; localNavigationController = [[UINavigationController alloc] initWithRoot ViewController:thirdViewController]; [localNavigationController.tabBarItem initWithTitle:@"Misc" image:[UIImage imageNamed:@"favorites.png"] tag:3]; thirdViewController.navigationItem.title=@"Misc"; [localControllersArray addObject:localNavigationController]; [localNavigationController release]; [thirdViewController release]; // load up our tab bar controller with the view controllers tabBarController.viewControllers = localControllersArray; // release the array because the tab bar controller now has it [localControllersArray release]; // add the tabBarController as a subview in the window [window addSubview:tabBarController.view]; // need this last line to display the window (and tab bar controller) [window makeKeyAndVisible]; return YES; } 捕获 Tab 切换事件,获取当前活动的 Tab 索引和 UIViewController 对象,代码如下。 - (void)tabBarController:(UITabBarController *)barController didSelectView Controller:(UIViewController *)viewController{ NSLog(@"currentController index:%d",viewController, tabBarController.selectedIndex); UIViewController *currentController = tabBarController.selectedView Controller; NSLog(@"currentController: %@",currentController); } 切换不同的 Tab 时,只需要设置 UITabBarController 的 selectedIndex 属性即可,代码 如下。 tabBarController.selectedIndex = 2; 本节相关的完整 Xcode 工程源代码文件请参考本书附带的光盘中的 Lessons2 实例。 3.12.3 使用 UISplitViewController 组织和管理 UIView UISplitViewController 属于 iPad 特有的界面控件,适合用于主从界面的情况(Master view→Detail view),Detail view 跟随 Master view 进行更新,如图 3-27 所示,屏幕左边 (Master View)是主菜单,单击每个菜单则屏幕右边(Detail View)就进行刷新,屏幕右边 ┃第 3 章 iPhone SDK 开发基础┃ 的界面内容又可以通过 UINavigationController 进行组织,以便用户进入 Detail View 进行更 多操作,用户界面以这样的方式进行组织,使得程序内容清晰,非常有条理,是组织用户 界面导航很好的方式,有关 UISplitViewController 的具体使用,将在后面的章节进行介绍。 图 3-27 UISplitViewController 程序框架实例界面 重要提示:UIView 的 tag 属性在 iPhone 程序开发中非常重要,因为几乎所有 的 View 之间的管理都是依靠 tag 来进行索引和查找。 iPhone 程序框架小结: (1)使用 UIViewController 组织和管理你的 UIView; (2)使用.plist 文件、Core Data 或者自定义数据持久方式管理你的缓存和持久数据; (3)使用 UINavigationController、UITabBarController,或者 UISplitViewController 管 理你的 UIViewController。 练习: (1)通过 View 的 tag 属性对 UIView 进行管理。 (2)通过 UINavigationController 对 UIViewController 进行管理。 (3)通过 UITabBar 对 UIViewController 进行管理。 (4)通过 UISegmentControl 对 UIViewController 进行管理。 3.29 OpenFlow 编程 当用户界面需要按页面显示图片时,使用 OpenFlow 库提供的功能,将要显示的用户 界面图片分页进行显示会使编程工作变得非常快捷。该库提供了与 OS X 桌面 Finder 程序 相同的视觉效果,如图 3-46 所示就是一个使用 OpenFlow 库逐页进行图片显示的程序,用 户按下屏幕即可进行左右滚动显示,双击图片即可对当前显示的图片进行选取操作。 图 3-46 OpenFlow 编程实例界面 程序在视图控制器的viewDidAppear()中使用refreshCoverFlow()函数初始化OpenFlow 库,通过 setNumberOfImages()函数设置图片数量,代码如下。 ┃第 3 章 iPhone SDK 开发基础┃ // RootViewController.m - (void)refreshCoverFlow{ CGRect bounds = [[UIScreen mainScreen] bounds]; AFOpenFlowView *coverFlowView = (AFOpenFlowView*)[self.view viewWithTag:kTagCoverflow]; if(coverFlowView != nil) [coverFlowView removeFromSuperview]; coverFlowView = [[AFOpenFlowView alloc] initWithFrame:CGRectMake(0, -30, bounds.size.width, COVERFLOWHEIGHT)]; coverFlowView.dataSource = self; coverFlowView.viewDelegate = self; coverFlowView.defaultImage = [self defaultImage]; coverFlowView.tag = kTagCoverflow; [self.view addSubview:coverFlowView]; NSInteger count = [self numberOfAnimals]; [coverFlowView setNumberOfImages:count]; //... [coverFlowView release]; } 并在 loadView()中初始化图片,将图片从资源中加载并保存在一个 NSMutableArray 类型的变量 imageArray 中,代码如下。 - (BOOL)doAddAnimal:(NSString *)name Image:(NSString *)imageName{ UIImage *image = [UIImage imageNamed: imageName]; if(image == nil) return FALSE; CGSize size = CGSizeMake(179, 208); [imageArray addObject:[self resizeImage:image scaledToSize:size]]; return TRUE; } 在 OpenFlow 库的 requestImageForIndex delegate 方法中直接通过 NSMutableArray 的 索引作为 OpenFlow 库的图片索引,并通过该索引设置和获取具体图片,代码如下。 // PageViewController.m - (void)openFlowView:(AFOpenFlowView *)openFlowView requestImageForIndex: (int)index{ UIImage *image = [imageArray objectAtIndex:index]; [openFlowView setImage:image forIndex:index]; } 笔者在 OpenFlow 库 AFOpenFlowView.m 文件的 touchesEnded()函数中增加了双击回 调接口,以便在用户双击图片时通知库的调用者,代码如下。 //AFOpenFlowView.m - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if(((UITouch *)[touches anyObject]).tapCount == 2){ if ([self.viewDelegate respondsToSelector:@selector(openFlowView: coverViewDoubleClick:)]) [self.viewDelegate openFlowView:self coverViewDoubleClick: selectedCoverView.number]; } [super touchesEnded:touches withEvent:event]; } 库的调用者 RootViewController 类通过接口函数 coverViewDoubleClick()即可处理用 户双击事件,代码如下。 - (void)openFlowView:(AFOpenFlowView *)openFlowView coverViewDoubleClick:(int)index{ NSLog(@"coverViewDoubleClick called!"); [self showPaintingViewController]; } 本节相关的完整 Xcode 工程源代码文件请参考本书附带的光盘中的 OpenFlow 工程。 3.30 UIPageControl 编程 当用户界面需要按页面进行显示时,使用 iOS 提供的 UIPageControl 控件将要显示的 用户界面内容分页进行显示会使编程工作变得非常快捷,如图 3-47 所示就是一个使用 UIPageControl 控件逐页进行图片显示的程序,用户按下屏幕即可进行左右滚动显示,在 屏幕的正上方使用白色的点显示当前滚动到的页面位置。 ┃第 3 章 iPhone SDK 开发基础┃ 图 3-47 UIPageControl 编程实例界面 程序自定义一个 SwipeView 类,该类通过子类化 UIView 类并重载其 touchesMoved() 方法捕获用户滚动的方向,类的定义如下。 // SwipeView.h #import #import @interface SwipeView : UIView { CGPoint startTouchPosition; NSString *dirString; UIViewController *host; } - (void) setHost: (UIViewController *) aHost; @end // SwipeView.m #import "SwipeView.h" @implementation SwipeView - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { // Initialization code } return self; } - (void) setHost: (UIViewController *) aHost { host = aHost; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; startTouchPosition = [touch locationInView:self]; dirString = NULL; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = touches.anyObject; CGPoint currentTouchPosition = [touch locationInView:self]; #define HORIZ_SWIPE_DRAG_MIN 12 #define VERT_SWIPE_DRAG_MAX 4 if (fabsf(startTouchPosition.x - currentTouchPosition.x) >= HORIZ_SWIPE_DRAG_MIN && fabsf(startTouchPosition.y - currentTouchPosition.y) <= VERT_SWIPE_DRAG_MAX) { // Horizontal Swipe if (startTouchPosition.x < currentTouchPosition.x) { dirString = kCATransitionFromLeft; } else dirString = kCATransitionFromRight; } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if (dirString) [host swipeTo:dirString]; } @end 在捕获用户滚动的方向后 ,SwipeView 类通过用户设置的 host 成员变量回调其 ┃第 3 章 iPhone SDK 开发基础┃ swipeTo()方法,host 成员变量在类中定义为 UIViewController,在编译时编译器会产生警 告,这里不用管它,只需要 SwipeView 类的使用者设置 host 成员变量并实现 swipeTo()方 法即可。 SwipeView 类的使用者为 PageViewController 类,该类实现程序的主界面,在这个自 定义的 UIViewController 类中实现 swipeTo()方法,代码如下。 // PageViewController.m - (void) swipeTo: (NSString *) aDirection{ UIPageControl *pageControl = [[[contentView superview] subviews] lastObject]; if ([aDirection isEqualToString:kCATransitionFromRight]) { if (currentPage == 5) return; [pageControl setCurrentPage:currentPage + 1]; } else { if (currentPage == 0) return; [pageControl setCurrentPage:currentPage - 1]; } [self pageTurn:pageControl]; } 在该回调方法中根据用户滚动的方向来设置 UIPageControl 的 currentPage 属性,如果 是向右方滚动则页面计数加一,如果用户滚动的方向是向左,则页面计数减一。设置 UIPageControl 的 currentPage 属性以后,PageViewController 对象再调用其 pageTurn()方法 交换页面显示内容,并将图片显示出来,代码如下。 - (void) pageTurn: (UIPageControl *) pageControl{ CATransition *transition; int secondPage = [pageControl currentPage]; if ((secondPage - currentPage) > 0) transition = [self getAnimation:@"fromRight"]; else transition = [self getAnimation:@"fromLeft"]; UIImageView *newView = (UIImageView *)[[contentView subviews] objectAtIndex:0]; [newView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"ipad_ wallpaper%02d.jpg", secondPage + 1]]]; [contentView exchangeSubviewAtIndex:0 withSubviewAtIndex:1]; [[contentView layer] addAnimation:transition forKey:@"transitionView Animation"]; currentPage = [pageControl currentPage]; } 在主 pageTurn()方法实现中,PageViewController 类通过 UIView 的 exchangeSubview AtIndex()方法实现页面内容的切换。 本节相关的完整Xcode工程源代码文件请参考本书附带的光盘中的PageControl工程。 3.31 自定义仪表控件 在 iOS 开发中,因为程序的需要,有时要自行绘制 iPhone SDK 没有提供的界面控件, 通常使用 QuartzCore.framework 即可画出你所需要的各种图形,在这里我们实现一个圆形 的“仪表盘”控件,控件的外观如图 3-48 所示,用户可以通过旋转仪表控件的指针来设 置程序需要的各种系统参数。 ┃第 3 章 iPhone SDK 开发基础┃ 图 3-48 “仪表盘”控件 控件使用两个 UIView 来实现仪表控件,并通过 CGAffineTransform 类来实现仪表指 针的旋转,控件在 UIDialView 类中实现,UIDialView 类的定义如下。 // UIDialView.h #import @protocol UIDialViewDelegate @optional - (void)dialValue:(int)tag Value:(float)value; @end @interface UIDialView : UIView { id delegate; NSTimer *timer; UIImageView *iv; float maxValue,minValue; CGAffineTransform initialTransform ; float currentValue; } @property(nonatomic,assign)iddelegate; @property CGAffineTransform initialTransform; @property float currentValue; @end 在 UIDialView 类的实现文件中,通过 init()方法读取图片文件初始化控件背景和指针, 代码如下。 // UIDialView.m #import "UIDialView.h" @interface UIDialView() -(void)spin:(NSTimer *)timer; -(float) goodDegrees:(float)degrees; @end #define degreesToRadians(degrees) (M_PI * degrees / 180.0) #define radiansToDegrees(radians) (radians * 180 / M_PI) static CGPoint delta; static float deltaAngle; static float currentAngle; @implementation UIDialView @synthesize initialTransform,currentValue; - (void)dealloc { [iv release]; [super dealloc]; } @synthesize delegate; - (id)init{ if ((self = [super init])) { self.userInteractionEnabled = YES; iv =[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"knob. png"]]; UIImage *backgroundTile = [UIImage imageNamed: @"clock.png"]; UIColor *backgroundPattern = [[UIColor alloc] initWithPatternImage: backgroundTile]; self.contentMode = UIViewContentModeCenter; [self setBackgroundColor:backgroundPattern]; [backgroundPattern release]; iv.backgroundColor = [UIColor clearColor]; iv.autoresizesSubviews= YES; self.frame = CGRectMake(0, 0, iv.frame.size.width, iv.frame.size. height); [self addSubview:iv]; [self bringSubviewToFront:iv]; [iv release]; currentValue = 0; currentAngle = 0; deltaAngle = 0.0; } return self; } ┃第 3 章 iPhone SDK 开发基础┃ 在 UIView 的 touchesBegan()方法中捕获用户 Touch 点的位置,并根据此位置使用 atan2()函数计算出控件的初始化角度,代码如下。 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *thisTouch = [touches anyObject]; delta = [thisTouch locationInView:self]; float dx = delta.x - iv.center.x; float dy = delta.y - iv.center.y; deltaAngle = atan2(dy,dx); initialTransform = iv.transform; } 在用户的旋转过程中通过设置指针UIView 对象的 transform属性实现仪表控件指针伴 随用户手指的旋转而旋转,代码如下。 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint pt = [touch locationInView:self]; float dx = pt.x - iv.center.x; float dy = pt.y - iv.center.y; float ang = atan2(dy,dx); if (deltaAngle == 0.0) { deltaAngle = ang; initialTransform = iv.transform; }else{ float angleDif = deltaAngle - ang; CGAffineTransform newTrans = CGAffineTransformRotate(initialTransform, -angleDif); iv.transform = newTrans; float diffValue = [self goodDegrees:radiansToDegrees(angleDif)]; currentValue = maxValue - ((maxValue - minValue)/300)*diffValue; if(currentValue > 100) currentValue = 100; } if (delegate != nil) { [delegate dialValue:self.tag Value:currentValue]; } } 客户通过实现 UIDialViewDelegate 接口协议的 dialValue()方法而得到控件的通知消 息,代码如下。 // DialViewController.h #import #import "UIDialView.h" @interface DialViewController : UIViewController< UIDialViewDelegate> { UIDialView *dialView; UILabel *myLabel; } - (void)dialValue:(int)tag Value:(float)value{ NSString *str = [NSString stringWithFormat:@"%.1f",v*100]; [myLabel performSelector:@selector(setText:) withObject:str]; } 本节相关的完整 Xcode 工程源代码文件请参考本书附带的光盘中的 DialControl 工程。 3.32 本章总结 本章介绍使用 iPhone SDK 进行软件开发所涉及的主要基础知识,包括 SDK 的主要框 架、系统结构,使用 Interface Builder 进行用户界面开发,iOS 的事件响应机制,用户界面 核心类 UIView 解析,商业 iOS 软件的主要框架类型分析,动画实现以及 SDK 主要用户 界面控件的实例剖析。这些知识涵盖了使用 iPhone SDK 进行企业应用开发所需要的主要 基础技术和编程要点,每个技术要点都包含实际应用的商业代码,掌握这些基础技术以及 在这些实例的基础上修改和扩展功能,将在实际的 iOS 商业应用中极大地减少开发和测试 时间,重复利用这些已实现的功能代码将节约您宝贵的项目开发时间。 第 5 章┃ iPhone 企业应用实例分析 By other's faults, wise men correct their own. 他山之石,可以攻玉。 ——《旧约·箴言》 5.1 综合应用概述 本章将通过完整的商业项目将本书前面介绍的 iPhone 开发技术要点综合起来,组织 成为一个整体,让读者在掌握局部知识要点的基础上,再通过完整的实例掌握商业项目全 局的组织设计方式,让读者在了解 iPhone 编程技术要点的同时,又具备将这些技术要点 综合起来在实际中应用的能力,通过实例学习,有利于读者灵活地将以前掌握的知识应用 到实际的开发项目中。 5.2 系统介绍 这是一个通过手机进行企业工作流和文档管理的项目,要求基于 Web 技术、多层架 构、业务层使用 Web Service 提供服务,客户端需要支持 iPhone、Android、Blackberry 和 Windows Mobile 平台,系统框架如图 5-1 所示。 图 5-1 系统架构 ┃第 5 章 iPhone 企业应用实例分析┃ 5.3 系统需求和主要用例 项目名称:WebDoc Mobile 系统需求: (1)用户认证:用户必须登录才可以使用本应用。 (2)搜索功能:通过文档主题、代码等进行搜索以及通过我的文档、部门文档进行归 类和搜索。 (3)查看文档细节:文档作者/创建日期等详细资料;文档相关附件;文档变更历史。 (4)工作流处理:允许用户对文档进行工作流处理。 (5)性能:内存优化管理并进行缓存处理以提高响应时间,并最小化客户端对服务器 的请求数量。 (6)通信:服务器和客户端采用 Web Service 进行通信。 (7)加密:网络数据必须进行加密。 (8)网络:网络连接状态侦测,并采用异步网络请求。 (9)错误处理:能够捕捉程序异常,没有宕机情况。 (10)其他:易于维护和扩展。 主要用例如图 5-2、图 5-3 所示。 说明: (1)查看我的文档:列出所有我要处理的文档。 (2)查看部门文档:列出所有部门处理中的文档。 (3)搜索文档:根据文档处理状态、部门、用户等条件搜索文档。 (4)文档统计:根据时间段、处理部门、责任人等进行统计,并以图表形式显示。 (5)上传文档和下载文档附件:用户通过手机上传、下载和查看文档。 (6)工作流处理:设置文档在当前工作流中可以设置的状态、添加注释等。 图 5-2 主要用例 1 图 5-3 主要用例 2 ┃第 5 章 iPhone 企业应用实例分析┃ 5.4 程序处理流程 程序处理流程总体框图如图 5-4 所示。 图 5-4 程序处理流程图 (1)用户启动程序时,显示闪屏。 (2)显示系统主菜单,主要有“我的文档”、“部门文档”、“文档搜索”和“统计图查 询” 。 (3)用户选择“我的文档”以后显示需要我处理的文档列表。 (4)用户选择“部门文档”以后显示部门列表。 (5)用户选择“文档搜索”以后显示搜索条件设置界面。 (6)用户选择部门列表中的部门以后显示部门处理中的文档列表。 (7)用户设置搜索条件,单击搜索以后显示搜索结果文档列表。 (8)在文档列表界面显示文档名称、文档标识码,并可以前后翻页。 (9)用户选择文档列表中的文档时,显示该文档的详情,详情分为 4 个页面显示,第 1 页显示文档名称、作者、日期、状态等详细资料;第 2 页显示文档的附件,用户单击附 件时可以将附件下载到手机;第 3 页显示文档处理历史记录;第 4 页显示文档工程流处理 界面。 (10)用户选择“统计图查询”以后显示统计图列表。 (11)用户选择统计图列表中的记录时显示统计图。 (12)用户单击 Info 按钮时显示程序版本等信息。 5.6 程序框架分析 WebDoc Mobile 项目是典型的多层流程型系统,所以系统主要使用 UINavigation Controller 进行用户界面的导航,这样当用户从上一层界面进入下一层界面,在下一层界 面的事情处理完以后,又可以方便地返回到上一层界面,在用户登录系统以后,系统显示 主菜单,如图 5-6 所示。 主菜单分为 4 个选项,即“我的文档”、“部门文档”、“高级搜索”和“统计图”, 主 菜单在 MainViewController 类中实现,该类使用 UITableView 来对菜单项进行管理, UITableView 的数据源使用一个 NSMutableArray 来提供表格数据,表格绘制时,使用以下 命令。 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section{ ┃第 5 章 iPhone 企业应用实例分析┃ 图 5-6 系统主菜单界面 return menuList.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{ NSDictionary *dataDictionary = [menuList objectAtIndex:indexPath.row]; cell.textLabel.text = [dataDictionary valueForKey:kTitleKey]; return cell; } 返回表格行数和每行的具体内容,每行表格数据包含下一层 ViewController 界面的标 题和类名称,当用户单击主菜单的菜单项时,程序先使用该类名称调用 NSClassFromString() 创建类对象,然后再创建 ViewController 对象,并将 ViewController 加入 UINavigation Controller 中进行界面显示。 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath{ targetViewController = [[NSClassFromString(viewControllerName) alloc] initWithNibName:viewControllerName bundle:nil]; [self.navigationController pushViewController:targetViewController animated:YES]; } 在用户选择“我的文档”或者选择“部门文档”界面的具体部门后,以及使用“文档 搜索”功能搜索文档后,程序就显示文档列表,如图 5-7 所示。 图 5-7 文档列表界面 文档列表显示使用 DocListViewController 类实现,该类包含文档记录分页,前后导航 功能,当记录超过每页记录显示的最大行数时,用户可以使用前向和后向箭头进行翻页, 另外在用户进行搜索以后,程序也使用这个类来显示搜索结果。 DocListViewController 类包含一个 UITableView 成员变量,程序使用这个表格来显示 文档列表,表格的数据源使用一个 NSMutableArray 来存储和提供数据,这个数组的每个 元素都是一个 DocumentDetailViewController 类实例,在文档列表显示前使用一个遍历来 创建这些 DocumentDetailViewController 类实例。 for(i = 0; i < nResult; i++){ DocumentDetailViewController *presidentsViewController = [[NSClassFromString(viewControllerName) alloc] initWithNibName:viewControllerName bundle:nil]; Document *doc = [objects objectAtIndex:i]; presidentsViewController.title = doc.documentName; [presidentsViewController setDocument:doc]; [controllers addObject:presidentsViewController]; ┃第 5 章 iPhone 企业应用实例分析┃ [presidentsViewController release]; } 当用户单击文档列表中的某个文档时,程序就从数组中取出对应的元素,然后显示 DocumentDetailViewController 对象。 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; NSUInteger row = [indexPath row]; if(self.controllers != nil){ DocumentDetailViewController *nextController = [self.controllers objectAtIndex:row]; //preload detail, attachment and history. [nextController preLoadData]; //clear cache [self handleWithCache]; //push document detail view... [self.navigationController pushViewController:nextController animated:YES]; } } 因为 DocumentDetailViewController 类需要包含的内容较多,所以程序使用分页显示 的方式来组织这些内容,DocumentDetailViewController 类使用一个 UISegmentedControl 类来管理文档详情、文档附件、文档历史和工作流 4 个具体页面,如图 5-8 所示。 这样,当用户进入文档详情的时候,就可以方便地在文档附件、文档历史等页面之间 进行切换,在 DocumentDetailViewController 类的 viewDidLoad()方法中通过 addTarget()函 数设置 UISegmentedControl 页面切换时的响应函数,这个响应函数在 UISegmentedControl 对象创建时进行设置,这里设置的是 didChangeSegmentControl 函数。 self.segmentedControl = [[UISegmentedControl alloc] initWithItems:segmentTitles]; [self.segmentedControl addTarget:self action:@selector(didChangeSegmentControl:) forControlEvents:UIControlEventValueChanged]; 当用户在页面之间切换时,这个函数就得到调用,函数首先将当前活动页面移除,然 后再激活并显示用户选择的页面。 图 5-8 文档详情界面 - (void)didChangeSegmentControl:(UISegmentedControl *)control { if (self.activeViewController) { [self.activeViewController viewWillDisappear:NO]; [self.activeViewController.view removeFromSuperview]; [self.activeViewController viewDidDisappear:NO]; } self.activeViewController = [self.segmentedViewControllers objectAtIndex: control.selectedSegmentIndex]; [self.activeViewController viewWillAppear:YES]; [self.view addSubview:self.activeViewController.view]; [self.activeViewController viewDidAppear:NO]; } 这样就实现了在 4 个页面之间进行切换、隐藏和显示的功能。DocumentDetailView Controller 类通过 UISegmentedControl 类来组织页面内容是程序的主体所在,也是编程的 重点,该类通过另外 4 个类来组织和管理页面内容,另外 4 个类分别是 DocDetailView Controller 类,用来显示文档明细;DocFilesViewController 类,用来管理文档附件; DocHistoryViewController 类,用来管理文档变更历史;DocWorkflowViewController 类, 实现工作流管理。 ┃第 5 章 iPhone 企业应用实例分析┃ 当用户单击“部门文档”主菜单时,程序显示部门列表界面,如图 5-9 所示。 当用户选择具体部门时,程序通过 Web Service 查询服务器端的后台数据库,然后将 服务器返回数据进行显示,即显示用户所选部门当前处理中的文档列表。 当用户选择“统计图”主菜单时,程序列出系统现有的统计图列表,如图 5-10 所示。 在用户单击统计图明细图标 时,程序通过 Web Service 查询服务器端后台数据库, 并根据返回数据将统计图显示在手机上,如图 5-11 所示。 图 5-9 部门列表界面 图 5-10 统计图列表 图 5-11 统计图界面 5.7 技术要点分析 5.7.1 异步网络通信 在 WebDoc Mobile 项目中,系统的异步网络通信功能在 AsyncNet 类中实现,系统使 用 AsyncNet 类来封装对 NSURLConnection 的操作,在 iOS 开发中通常使用 NSOperation 来处理多任务的并发问题,因为 NSURLConnection 本身已经支持异步操作,所以没有必 要再使用 NSOperation 来对每个请求进行包装,而是使用一个 NSMutableArray 来存取请求队 列,并使用一个 NSMutableDictionary 来将请求对象和响应数据进行关联,NSURLConnection 对象作为 Key,请求对象作为值,增加关联的代码: NSMutableDictionary *requests; AsyncNetRequest *request = [[AsyncNetRequest alloc] init]; [requests setObject:request forKey: [NSValue valueWithNonretainedObject:con]]; [request release]; … 5.7.2 Core Data 缓存数据 在进行 iPhone 软件开发时,使用 Core Data 进行数据缓存或者管理持久数据是一项必 须掌握的基本技术。前面我们已经做过介绍,和前面使用 Core Data 管理“动物园”项目 持久数据不同的是,程序在这里没有使用表之间的关联关系,而只是定义文档、文档附件、 文档历史以及统计图 4 种对象对应的数据库模型,用来缓存服务器返回的数据,并不作为 关系数据和持久数据使用,在每次程序启动时都会清空数据库,重新使用服务器返回的最 新数据,Core Data 只起到数据缓存的作用,当数据从服务器返回以后,在第二次使用时 程序从缓存取数据而不是从服务器取数据,这样可以提高反应速度,文档对象对应的数据 库模型包含的字段定义如下。 // Document.h #import @interface Document: NSManagedObject{ } … 5.7.3 RSA 算法加解密 在 WebDoc Mobile 项目中,iPhone 客户端和服务器端(使用 Microsoft .NET 技术 )采 用 Web Service 进行相互通信,通信双方需要将数据进行加密处理,以保证网络通信的安 全性,未经认证的客户端 Web Service 调用将不能在服务器端执行,系统采用业界目前广 ┃第 5 章 iPhone 企业应用实例分析┃ 泛采用的 PKI(公钥基础设施)技术进行用户认证管理,使用 RSA 算法进行加解密,有 关 RSA 算法加解密的具体内容在本书前面的章节已经做了介绍,实现的细节请参考本书 附带的光盘中的 DocMobile 工程,这里就不再详述。 5.7.4 自定义控件制作 在 WebDoc Mobile 项目中,由于用户界面的需要,系统制作了一些自定义的界面控件, 其中包括与桌面软件类似的 ComboBox 界面控件,如图 5-12 所示。 图 5-12 自定义 ComboBox 控件 该控件用于用户登录和高级搜索时,提供下拉多项目选择,程序使用 UITextField 类、 UIPickerView 类和 UIToolbar 类三个主要类实现,具体的实现方法在前面的章节已经做了 具体介绍。 自定义搜索控件,控件外观如图 5-13 所示。 图 5-13 自定义搜索控件 该控件提供在许多数据记录中进行选择过滤的功能,当用户输入一个字符或者单词, 程序实时从数据记录中找出开头字符或者记录中包含该字符或者单词的记录,把记录进行 实时过滤。这样,用户就不用在很长的列表里面查找,而是从过滤后的少量记录里面挑选, 该控件在需要用户从非常多的选项中做选择的时候,可以作为界面设计元素。控件使用 SearchViewController类实现,SearchViewController类内部使用UITableView和UISearchBar 联合实现记录过滤功能,当用户输入字符时,程序使用 NSString 类的 rangeOfString 方法 对记录进行过滤,并使用过滤后的记录刷新 UITableView 的内容,代码如下。 - (void) searchTableView { NSString *searchText = search.text; for (NSString *sTemp in tempArray) { NSRange titleResultsRange = [sTemp rangeOfString:searchText options: NSCaseInsensitiveSearch]; if (titleResultsRange.length > 0) [searchArray addObject:sTemp]; } } ┃第 5 章 iPhone 企业应用实例分析┃ 本节控件实现和使用相关的完整源代码文件请参考本书附带的光盘中的 DocMobile 工程。 5.7.5 表格控件定制 在 iOS 开发中,UITableView 是使用频率最高的控件之一,为了实现各种用户界面的 需要,经常需要对表格的每一行进行定制,如图 5-14 所示是文档历史的显示界面。 图 5-14 文档历史界面 程序通过设置 cell.textLabel.text 和 cell.detailTextLabel.text 来达到如图 5-14 所示的显 示效果,代码如下。 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *AttachmentsCell= @"HistoryCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: AttachmentsCell]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyle Value2 reuseIdentifier: AttachmentsCell] autorelease]; } if(records != nil){ NSUInteger row = [indexPath row]; DocumentHistory *history = [records objectAtIndex:row]; cell.textLabel.text = history.historyText; cell.detailTextLabel.text = history.historyTitle; cell.detailTextLabel.numberOfLines = 2; cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap; } return cell; } 通常使用子类化 UITableViewCell 类的方法来定制表格控件,然后在 UITableView 进 行表格绘制调用 cellForRowAtIndexPath()时,使用该定制的子类呈现用户界面。在统计图 列表的实现类 StatisticsViewController 中就使用了一个自定义的 IndicatorSubviewCell 类来 定制每一行的显示,该类是 UITableViewCell 类的子类,如图 5-15 所示是统计图表格控件 制作出来的效果图。 图 5-15 统计图界面 IndicatorSubviewCell 类使用.xib 文件来创建界面显示内容,这样可以使用 Interface Builder 可视化地创建各种界面元素,Interface Builder 提供了一个“Table View Cell”的设 ┃第 5 章 iPhone 企业应用实例分析┃ 计控件,专门用来创建各种自定义表格控件,你只需要像使用普通 View 一样将需要的界 面元素拖放进视图,并将其连接到相应的类成员即可,如图 5-16 所示是统计图表格控件 在 Interface Builder 中的设计图。 图 5-16 统计图控件设计界面 我们看到上面的设计视图包括两个 UILabel 和一个 UIImageView,和上面的表格控件 效果图并不一致,少了最右边的那个放大镜 图标,这是因为最后这个图标是一个可单 击区域,用户单击这个区域以后程序显示具体的统计图,这个区域是由程序进行创建而不 是通过 Interface Builder 可视化创建的,设计视图对应的类定义如下。 //IndicatorSubviewCell.h #import #import "IndicatorCell.h" @interface IndicatorSubviewCell : UITableViewCell { IBOutlet UIImageView *iconView; IBOutlet UILabel *nameLabel; IBOutlet UILabel *priceLabel; } @end … 5.7.6 自定义 UIToolbar 在 WebDoc Mobile 项目中,程序使用自定义的 UIToolbar 来实现工作流设置的输入确 认,虽然 UIActionSheet 类和 UIToolbar 类都可以提供带按钮的用户输入界面,但前者属 于弹出式的模式窗口,而后者则是非弹出式的界面输入元素,工作方式不一样,因为在 DocumentDetailViewController 类中包含文档详情、文档附件、文档历史和工作流 4 个 UISegmentedControl 页面,“文档附件”页面需要提供 UIToolbar 按钮来引导用户浏览手机 本地目录,以便选择需要上传的文件,“工作流”页面需要提供 UIToolbar 按钮来确认工 作流设置,而其他两个页面不需要 UIToolbar 按钮,为了保持界面的一致性,程序通过用 户当前选择的页面来判断是否该隐藏还是显示 UIToolbar 按钮,并根据不同页面做出不同 的响应,如图 5-17 所示是带 UIToolbar 的工作流设置界面。 图 5-17 自定义 UIToolbar 用户界面 在 DocumentDetailViewController 类的实现中,程序定义一个 UIToolbar 类成员变量, 并在 viewWillAppear 函数中创建 UIToobar 对象,代码如下。 - (void)viewWillAppear:(BOOL)animated ┃第 5 章 iPhone 企业应用实例分析┃ { toolbar = [[UIToolbar alloc] init]; [self setNavigatinBarStyle:DEFAULT_STATUS_BAR_STYLE]; [toolbar sizeToFit]; CGFloat toolbarHeight = [toolbar frame].size.height; CGRect rootViewBounds = self.parentViewController.view.bounds; CGFloat rootViewHeight = CGRectGetHeight(rootViewBounds); CGFloat rootViewWidth = CGRectGetWidth(rootViewBounds); CGRect rectArea = CGRectMake(0, rootViewHeight - toolbarHeight, rootView Width, toolbarHeight); [toolbar setFrame:rectArea]; [self.navigationController.view addSubview:toolbar]; if(self.segmentedControl != nil){ if(self.segmentedControl.selectedSegmentIndex == 1|| self.segmentedControl.selectedSegmentIndex == 3){ NSMutableArray* toolbarItems = [[NSMutableArray arrayWithArray: toolbar.items] retain]; int a = [toolbarItems count]; if (a == 0 ) { infoButton = [[UIBarButtonItem alloc] initWithTitle:@"AttachFile" style:UIBarButtonItemStyleDone target:self action:@selector(browseFileSystem:)]; [toolbar setItems:[NSArray arrayWithObjects:infoButton,nil]]; } self.navigationController.toolbarHidden = YES; if(self.segmentedControl.selectedSegmentIndex == 3) infoButton.title = @"Done"; else infoButton.title = @"AttachFile"; }else{ self.navigationController.toolbarHidden = NO; } }else{ self.navigationController.toolbarHidden = NO; } } 程序在创建 UIToolbar 对象后 ,通过计算界面的宽度和高度 ,调用 UIView 的 setFrame() 方法将 Toolbar 放置在屏幕的最下方,并根据用户当前选择的 UISegmentedControl 页面, 隐藏或者显示 Toolbar,并在 Toolbar 上添加相应的按钮。 5.7.7 目录浏览器制作 在 WebDoc Mobile 项目中,用户需要将手机本地的文件上传到服务器端,iOS 并没有 提供目录浏览控件供开发者使用,所以只有自行开发实现目录浏览的功能,如图 5-18 所 示是实现的界面。 图 5-18 目录浏览控件用户界面 程序递归根目录下的所有目录和文件,目录以 图标显示,文件以 图标显示, 当用户单击目录图标时,程序列出该目录下的所有文件和目录,用户单击返回按钮又可以 返回上一层目录,当用户单击文件图标时,程序显示文件的详情,如修改日期、文件大小 等明细信息,如图 5-19 所示。 手机目录浏览器的实现,在 DirectoryViewController 类中,该类继承自 UITableView Controller,并实现 UINavigationControllerDelegate 接口,以便使用 UINavigationController 的导航功能,从文件目录的下一层方便地返回到目录的上一层,在 DirectoryViewController 类中使用一个 NSArray 类型的成员变量 directoryContents 来存储文件和目录名,并作为表 ┃第 5 章 iPhone 企业应用实例分析┃ 格控件的数据源,在创建 DirectoryViewController 对象以后,程序使用 NSFileManager 类 的 directoryContentsAtPath 方法列出指定目录下所有的文件和目录,并赋值给 directory Contents 成员变量。 图 5-19 文件详情用户界面 - (void) loadDirectoryContents { [directoryContents release]; directoryContents = [[NSMutableArray alloc] init]; directoryContents = [[NSFileManager defaultManager] directoryContentsAtPath: directoryPath]; [directoryContents retain]; } 在表格绘制时,查询 directoryContents 成员变量的元素个数就得到表格的行数,查询 表格行对应的数组元素就得到文件或者目录的名称,这样就可以正确显示每一行的内容。 … 5.7.8 文件上传和下载 5.7.7 节通过 UITableView 和 UINavigationController 两个类实现目录浏览器,在用户 浏览到想要上传的文件后,选择该文件就可以将其上传到服务器,在文件的上传过程中, 需要显示上传进度,以便用户了解当前的进度,如图 5-20 所示。 下面来看具体如何使用 UIAlertView 实现文件上传时的进度条显示功能。 图 5-20 文件上传用户界面 - (void) createProgressionAlertWithMessage:(NSString *)message withActivity:(BOOL)activity{ if(progressAlert != nil){ [progressAlert release]; progressAlert = nil; } // This timer takes the place of a real task amt = 0.0; timer = [NSTimer scheduledTimerWithTimeInterval: 0.5 target: self selector: @selector (handleTimer:) userInfo: nil repeats: YES]; ┃第 5 章 iPhone 企业应用实例分析┃ if(!progressAlert) { progressAlert = [[UIAlertView alloc] initWithTitle: message message: @"Please wait..." delegate: self cancelButtonTitle: nil otherButtonTitles: nil]; // Create the progress bar and add it to the alert if (activity) { UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicator ViewStyleWhite]; activityView.frame = CGRectMake(139.0f-18.0f, 80.0f, 37.0f, 37.0f); [progressAlert addSubview:activityView]; [activityView startAnimating]; [activityView release]; } else { progressView = [[UIProgressView alloc] initWithFrame:CGRectMake (30.0f, 80.0f, 225.0f, 90.0f)]; [progressAlert addSubview:progressView]; [progressView setProgressViewStyle: UIProgressViewStyleBar]; [progressView release]; } // Add a label to display download/upload size. UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(90.0f, 90.0f, 225.0f, 40.0f)]; label.backgroundColor = [UIColor clearColor]; label.textColor = [UIColor whiteColor]; label.font = [UIFont systemFontOfSize:12.0f]; label.text = @""; label.tag = 1; [progressAlert addSubview:label]; } [progressAlert show]; } 程序使用一个 NSTimer 来处理上传超时,若超时则终止上传操作。 - (void) handleTimer: (id) atimer { amt += 1; if(progressView != nil) [progressView setProgress: (amt / DOWNLOAD_TIMEOUT)]; if (amt > DOWNLOAD_TIMEOUT) { UILabel *label = (UILabel *)[progressAlert viewWithTag:1]; label.text = @"Sorry, Time Out..."; [atimer invalidate]; atimer = nil; [progressAlert dismissWithClickedButtonIndex:0 animated:TRUE]; [progressAlert release]; progressAlert = nil; } } 函数调用: [self createProgressionAlertWithMessage:@"Upload Document ..." withActivity:NO]; 文档附件上传界面如图 5-21 所示,用户单击“AttachFile”按钮,程序显示目录列表 供用户浏览和选择文件,用户选择具体的文件后即可将文件上传至服务器。 ┃第 5 章 iPhone 企业应用实例分析┃ 图 5-21 文档附件上传界面 本节相关的完整源代码文件请参考本书附带的光盘中的 DocMobile 工程。 5.8 本章总结 本章通过具体实例,介绍 iPhone 企业应用软件的开发过程、系统的架构、iPhone 客 户端程序的实现框架、程序处理流程及具体的技术实现要点,让读者了解到在实际项目 中,以前介绍过的 iPhone 开发知识是如何连接在一起、组织成为一个整体的,从而实现 项目的需求。本实例具有 iPhone 企业应用的典型性和代表性,所以通过本章项目的学习, 让读者了解到典型的 iPhone 企业应用系统架构、程序框架、编程可能涉及的相关知识, 掌握 iPhone 企业应用开发要点,以便将这些知识应用到具体的 iPhone 企业应用项目开发 中。
还剩58页未读

继续阅读

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

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

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

下载pdf