第4章 Cocoa Touch框架
Cocoa Touch是由苹果公司提供的专门用于程序开发的API,用于开发 iPhone、iPod和iPad上的软件。Cocoa Touch也是苹果公司针对iPhone应用程序快速开发提供的一个类库,这个库以一系列框架库的形式存在,支持开发人员使用用户界面元素构建图像化的事件驱动的应用程序。
4.1 Cocoa Touch基础
Cocoa Touch是一个开发iOS程序的重要框架之一,在本节的内容中,将简要介绍Cocoa Touch框架的基本知识,为读者步入本书后面知识学习打下基础。
4.1.1 Cocoa Touch概述
Cocoa Touch 框架重用了许多Mac系统的成熟模式,但是它更多地专注于触摸的接口和优化。UIKit 为您提供了在 iOS 上实现图形、事件驱动程序的基本工具,其建立在和 Mac OS X 中一样的 Foundation框架上,包括文件处理、网络、字符串操作等。
Cocoa Touch 具有和 iPhone 用户接口一致的特殊设计。有了 UIKit,我们可以使用 iOS 上的独特的图形接口控件、按钮,以及全屏视图的功能,您还可以使用加速仪和多点触摸手势来控制您的应用。
Cocoa Touch框架的主要特点如下所示。
1.基于 Objective-C 语言实现
大部分 Cocoa Touch 的功能是用 Objective-C 实现的。Objective-C 是一种面向对象的语言,它编译运行的速度令人难以置信。更值得一提的是采用了真正的动态运行时系统,从而增添了难能可贵的灵活性。由于 Objective-C 是 C 的超集,因而可以很容易地将C甚至C++代码添加到您的 Cocoa Touch 程序里。
当您的应用程序运行时,Objective-C运行时系统按照执行逻辑对对象进行实例化,而且不仅仅是按照编译时的定义。例如,一个运行中的Objective-C应用程序能够加载一个界面(一个由Interface Builder创建的nib文件),将界面中的Cocoa对象连接至您的程序代码,然后,一旦UI中的某个按钮被按下,程序便能够执行对应的方法。上述过程无需重新编译。
其实除了UIKit外,Cocoa Touch包含了创建世界一流iOS应用程序需要的所有框架,从三维图形到专业音效,甚至提供设备访问API以控制摄像头,或通过GPS获知当前位置。Cocoa Touch既包含只需要几行代码就可以完成全部任务的强大的Objective-C框架,也在需要时提供基础的C语言API来直接访问系统。
2.强大的Core Animation
通过Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。
3.强大的Core Audio
Core Audio是播放、处理和录制音频的专业技术,能够轻松为您的应用程序添加强大的音频功能。
4.强大的Core Data
提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。
4.1.2 Cocoa Touch中的框架
在Cocoa Touch中提供了如下几类十分常用的框架。
1.音频和视频
Core Audio
OpenAL
Media Library
AV Foundation
2.数据管理
Core Data
SQLite
3.图形和动画
Core Animation
OpenGL ES
Quartz 2D
4.网络
Bonjour
WebKit
BSD Sockets
5.用户应用
Address Book
Core Location
Map Kit
Store Kit
4.1.3 Cocoa Touch的优势
和Andriod和HP WebOS等开发平台相比,使用Cocoa Touch的最大优点是更加成熟。尽管iOS还是一种相对年轻的Apple平台,但是其Cocoa框架已经十分成熟了。Cocoa脱胎于在20世纪80年代中期使用的平台:NeXT Computer(一种NeXTSTEP)。在20世纪90年代初,NeXTSTEP发展成了跨平台的OpenStep。Apple于1996年收购了NeXT Computer,在随后的10年中,NeXTSTEP/OpenStep框架成为Macintosh开发的事实标准,并更名为Cocoa。其实我们在开发过程中会发现Cocoa仍然保留了其前身的痕迹:类名以NS开头。
注意:Cocoa和Cocoa Touch的区别
Cocoa是用于开发Mac OS X应用程序的框架。iOS虽然以Mac OS X的众多基本技术为基础,但并不完全相同。Cocoa Touch针对触摸界面进行了大量的定制,并受手持系统的约束。传统上需要占据大量屏幕空间的桌面应用程序组件被更简单的多视图组件取代,而鼠标单击事件则被“轻按”和“松开”事件取代。
开发者高兴的是:如果决定从iOS开发转向Mac开发,在这两种平台上将遵循很多相同的开发模式,而不用从头开始学习。
4.2 iPhone的技术层
Cocoa Touch 层由多个框架组成,它们为应用程序提供了核心功能。Apple以一系列层的方式来描述iOS实现的技术,其中每层都可以使用不同的技术框架组成。在iPhone的技术层中,Cocoa Touch层位于最上面。iPhone的技术层结构如图4-1所示。
图4-1 iPhone的技术层结构
在本节的内容中,将简单介绍iPhone各个技术层的基本知识。
4.2.1 Cocoa Touch 层
Cocoa Touch层是由多个框架组成的,它们为应用程序提供核心功能(包括iOS 4.x中的多任务和广告功能)。在这些框架中,UIKit是最常用的UI框架,能够实现各种绚丽的界面效果功能。Cocoa Touch层包含了构建iOS程序的关键framework。在此层定义了程序的基本结构,支持如多任务,基于触摸的输入,push notification等关键技术,以及很多上层系统服务。
1.Cocoa Touch层的关键技术
(1)多任务。
iOS SDK 4.0以及以后的SDK构建的程序中(且运行在iOS 4.0和以后版本的设备上),用户按下Home按钮的时候程序不会结束,它们会挪到后台运行。UIKit帮助实现的多任务支持让程序可以平滑切换到后台,或者切换回来。
为了节省电力,大多数程序进入后台后马上就会被系统暂停。暂停的程序还在内存里,但是不执行任何代码。这样程序需要重新激活的时候可以快速恢复,但是同时不浪费任何电力。然而,在以下原因下,程序也可以在后台下运行。
程序可以申请有限的时间完成一些重要的任务。
程序可以声明支持某种特定的服务,需要周期的后台运行时间。
程序可以使用本地通知在指定的时间给用户发信息,不管程序是否在运行。
不管你的程序在后台是被暂停还是继续运行,支持多任务都不需要你做什么额外的事情。系统会在切换到后台或者切换回来的时候通知程序。在这个时刻,程序可以直接执行一些重要的任务,例如保存用户数据等。
(2)打印。
从iOS 4.2开始,UIKit开始引入了打印功能,允许程序把内容通过无线网路发送给附近的打印机。关于打印,大部分重体力劳动由UIKit承担。它管理打印接口,和你的程序协作渲染打印的内容,管理打印机里打印作业的计划和执行。
程序提交的打印作业会被传递给打印系统,它管理真正的打印流程。设备上所有程序的打印作业会被排成队列,先入先出地打印。用户可以从打印中心程序看到打印作业的状态。所有这些打印细节都由系统自动处理。
注意:仅有支持多任务的设备才支持无线打印。你的程序可使用UIPrintInteractionController对象来检测设备是否支持无线打印。
(3)数据保护。
从iOS 4.0起引入了数据保护功能,需要处理敏感用户数据的应用程序可以使用某些设备内建的加密功能(某些设备不支持)。当程序指定某文件受保护的时候,系统就会把这个文件用加密的格式保存起来。设备锁定的时候,你的程序和潜在入侵者都无法访问这些数据。然而,当设备由用户解锁后,会生成一个密钥让你的程序访问文件。
要想实现良好的数据保护,需要仔细考虑如何创建和管理你需要保护的数据。应用程序必须在数据创建时确保数据安全,并适应设备上锁与否带来的文件可访问性的变化。
(4)苹果推通知服务。
从iOS 3.0开始,苹果发布了苹果推通知服务,这一服务提供了一种机制,即使你的程序已经退出,仍旧可以发送一些新信息给用户。使用这种服务,你可以在任何时候,推送文本通知给用户的设备,可以包含程序图标作为标识,发出提示声音。这些消息提示用户应该打开你的程序接收查看相关的信息。
从设计的角度看,要让iOS程序可以发送推通知,需要两部分的工作。首先,程序必须请求通知的发送,且在送达的时候能够处理通知数据。然后,你需要提供一个服务端流程去生成这些通知。这一流程发生在你自己的服务器上,和苹果的推通知服务一起触发通知。
(5)本地通知。
从iOS 4.0开始,苹果推出了本地通知,作为推通知机制的补充,应用程序使用这一方法可以在本地创建通知信息,而不用依赖一个外部的服务器。运行在后台的程序,可以在重要时间发生的时候利用本地通知提醒用户注意。例如,一个运行在后台的导航程序可以利用本地通知,提示用户该转弯了。程序还可以预定在未来的某个时刻发送本地通知,这种通知即使程序已经被终止也是可以被发送的。
本地通知的优势在于它独立于你的程序。一旦通知被预定,系统就会来管理它的发送。在消息发送的时候,甚至不需要应用程序还在运行。
(6)手势识别器。
从iOS 3.2起,引入了手势识别器,你可以把它附加到view上,然后用它们检测通用的手势,如划过或者捏合。附加手势识别器到view后,设置手势发生时执行什么操作。手势识别器会跟踪原始的触摸事件,使用系统预置的算法判断目前的手势。没有手势识别器,你就必须自己做这些计算,很多都相当复杂。
UIKit包含了UIGestureRecognizer 类,定义了所有手势识别器的标准行为。你可以定义自己的定制手势识别器子类,或者是使用UIKit提供的手势识别器子类来处理如下的标准手势:
单击(任何次数);
捏合缩放;
平移或者拖动;
划过(任何方向);
旋转(手指分别向相反方向);
长按;
文件共享支持。
文件共享功能是从iOS 3.2才开始引入的,利用它程序可以把用户的数据文件开发给iTunes 9.1以及以后版本。程序一旦声明支持文件共享,那么它的“/Documents@目录下的文件就会开放给用户。用户可以使用iTunes将文件放进去或者取出来。这一特性并不允许你的程序和同一设备里面的其他程序共享文件;那种行为需要用剪贴板或者文本交互控制对象(UIDocumentInteractionController)来实现。
要打开文件共享支持,需要做如下所示的工作。
在程序的Info.ppst文件内加入键UIFileSharingEnabled,值设置为YES。
把你要共享的文件放在程序的Documents目录内。
设备插到用户电脑时,iTunes在选定设备的程序页下面显示文件共享块。
用户可以在桌面上增加和删除文件。
由此可以看出,要想实现支持文件共享的程序,程序必须能够识别放到“Documents”目录中的文件,并且能够正确地处理它们。例如,程序应该用自己的界面显示新出现的文件,而不是把这些文件列在目录里,问用户该如何处理这些文件。
(7)点对点对战服务。
从iOS 3.0起引入的Game Kit框架提供了基于蓝牙的点对点对战功能。你可以使用点对点连接和附近的设备建立通信,是实现很多多人游戏中需要的特性。虽然这主要是用于游戏的,但是也可以用于其他类型的程序中。
(8)标准系统View Controller。
Cocoa Touch层的很多框架提供了用来展现标准系统接口的View Controller。你应该尽量使用这些View Controller,以保持用户体验的一致性。任何时候你需要做如下操作的时候,你都应该用对应框架提供的View Controller,具体说明如下所示。
显示和编辑联系人信息:使用Address Book UI框架提供的View Controller。
创建和编辑日历事件:使用Event Kit UI框架提供的View Controller。
编写email或者短消息:使用Message UI框架提供的View Controller。
打开或者预览文件的内容:使用UIKit框架里的UIDocumentInteractionController类。
拍摄一张照片,或者从用户的照片库里面选择一张照片:使用UIKit框架内的UIImagePickerController类。
拍摄一段视频:使用UIKit框架内的UIImagePickerController类。
(9)外部显示支持。
iOS 3.2开始,引入了外部显示支持,允许一些iOS设备可以通过支持的缆线连接到外部的显示器上。连接时,程序可以用对应的屏幕来显示内容。屏幕的信息,包括它支持的分辨率,都可以用UIKit框架提供的接口访问。你也可以用这个框架来把程序的窗口连接到一个屏幕或另外一个屏幕。
2.Cocoa Touch层包含的框架
在Cocoa Touch层中,主要包含如下所示的框架。
(1)UIKit。
UIKit提供了大量的功能。它负责启动和结束应用程序、控制界面和多点触摸事件,并让我们能够访问常见的数据视图(如网页以及Word和Excel文档等)。另外,UIKit还负责iOS内部的众多集成功能。访问多媒体库、照片库和加速计也是使用UIKit中的类和方法来实现的。
对于UIKitk框架来说,其强大的功能是通过自身的一系列的Class(类)来实现的,通过这些类实现建立和管理iPhone OS应用程序的用户界面接口、应用程序对象、事件控制、绘图模型、窗口、视图和用于控制触摸屏等接口功能。
iOS中的每个程序都在使用这个框架来实现如下所示的核心功能。
应用程序管理。
用户界面管理。
图形和窗口支持。
多任务支持。
支持对触摸的处理以及基于动作的事件。
展现标准系统View和控件的对象。
对文本和Web内容的支持。
剪切,复制和粘贴的支持。
用户界面动画支持。
通过URL模式和系统内其他程序交互。
支持苹果推通知。
对残障人士的易用性支持。
本地通知的预定和发送。
创建PDF。
支持使用行为类似系统键盘的定制输入View。
支持创建和系统键盘交互定制的Text view。
除了提供程序的基础代码支持,UIKit还包括了如下所示的设备支持特性。
加速度传感器数据。
内建的摄像头(如果有的话)。
用户的照片库。
设备名和型号信息。
电池状态信息。
接近传感器信息。
耳机线控信息。
(2)Map Kit。
Map Kit框架让开发人员在任何应用程序中添加Google地图视图,这包括标注、定位和事件处理功能。在iOS设备中使用Map Kit框架的效果如图4-2所示。
图4-2 使用 Map Kit框架的效果
从iOS 3.0开始,正式引入了Map Kit框架(MapKit.framework)提供了一个可以嵌入到程序里的地图接口。基于该接口的行为,它提供了可缩放的地图view,可标记定制的信息。你可以把它嵌入在程序的view里面,编程设置地图的属性,保存当前显示的地图区域和用户的位置。你还可以定义定制标记,或者使用标准标记(大头针标记),突出地图上的区域,显示额外的信息。
从iOS 4.0开始,这个框架加入可拖动标记和定制覆盖对象的功能。可拖动标记使开发者可以移动一个已经被放置到地图上的标记。覆盖对象提供了创建比标记点更复杂的地图标记的能力。你可以使用覆盖对象在地图上来放置信息,例如公交路线、选区图、停车区域、天气信息(如雷达数据)。
(3)Game Kit。
Game Kit框架进一步提高了iOS应用程序的网络交互性。Game Kit提供了创建并使用对等网络的机制,这包括会话发现、仲裁和语音聊天。可将这些功能加入到任何应用程序中,而不仅仅是游戏中。在当前市面中,有很多利用 Game Kit框架实现的iOS游戏产品,图4-3就是其中之一。
图4-3 用Game Kit框架实现的iOS游戏
从iOS 3.0版本开始,正式引入了Game Kit框架(GameKit.framework),支持在程序中进行点对点的网络通信。尤其是这个框架支持了点对点的连接和游戏内的语音通话功能。虽然这些功能主要是用于多人对战网络游戏,但是也可以在非游戏程序中使用。这个框架提供的网络功能是构建在Bonjour之上几个简单的类实现的。这些类抽象了很多网络细节,让没有网络编程经验的开发者也可以轻松地在程序中加入网路功能。
(4)Message UI/Address Book UI/Event Kit UI。
这些框架可以实现iOS应用程序之间的集成功能。框架Message UI、Address Book UI和Event Kit UI让我们可以在任何应用程序中访问电子邮件、联系人和日历事件。
(5)iAd。
iAd框架是一个广告框架,通过此框架可以在我们的应用程序中加入广告。iAd框架是一个交互式的广告组件,通过简单的拖放操作就可以将其加入到我们开发的软件产品中。在应用程序中,你无需管理iAd交互,这些工作由Apple自动完成。
从iOS 4.0版本开始,才正式引入了iAd框架(iAd.framework)支持程序中显示banner广告。广告由标准的view构成,你可以把它们插入到你的用户界面中,恰当的时候显示。View本身和苹果的广告服务通信,处理一切载入和展现广告内容以及响应单击等工作。
(6)Event Kit UI框架。
从iOS 4.0版本开始,正式引入了Event Kit UI框架(EventKitUI.framework),提供了用来显示和编辑事件的view controller。
4.2.2 多媒体层
当Apple设计计算设备时,已经考虑到了多媒体功能。iOS设备可创建复杂的图形、播放音频和视频,甚至可生成实时的三维图形。这些功能都是由多媒体层中的框架处理的。
1.AV Foundation
AV Foundation框架可用于播放和编辑复杂的音频和视频。该框架应用于实现高级功能,如电影录制、音轨管理和音频平移。
2.CoreAudio
Core Audio框架提供了在iPhone中播放和录制音频的方法;它还包含了Toolbox框架和AudioUnit框架,其中前者可用于播放警报声或导致短暂振动,而后者可用于处理声音。
3.CoreImage
使用Core Image框架,开发人员可在应用程序中添加高级图像和视频处理功能,而无需它们后面复杂的计算。例如,Core Image提供了人脸识别和图像过滤功能,可轻松地将这些功能加入到任何应用程序中。
4.CoreGraphics
通过使用Core Graphics框架,可在应用程序中添加2D绘画和合成功能。在本书的内容中,大部分情况下都将在应用程序中使用现有的界面类和图像,但可使用Core Graphics以编程方式操纵iPhone的视图。
5.Core Text
对iPhone屏幕上显示的文本进行精确的定位和控制。应将Core Text用于移动文本处理应用程序和软件中,它们需要快速显示和操作显示高品质的样式化文本。
6.ImageI/O
Image I/O框架可用于导入和导出图像数据和图像元数据,这些数据可以iOS支持的任何文件格式存储。
7.Media Player
Media Player框架让开发人员能够使用典型的屏幕控件轻松地播放电影,您可在应用程序中直接调用播放器。
8.OpenGLES
OpenGL ES是深受欢迎的OpenGL框架的子集,适用于嵌入式系统(ES)。OpenGL ES可用于在应用程序中创建2D和3D动画。要使用OpenGL,除Obj ective-C知识外还需其他开发经验,但可为手持设备生成神奇的场景——类似于流行的游戏控制台。
9.QuartzCore
Quartz Core框架用于创建这样的动画,即它们将利用设备的硬件功能。这包括被称为Core Animation的功能集。
4.2.3 核心服务层
核心服务层用于访问较低级的操作系统服务,如文件存取、联网和众多常见的数据对象类型。您将通过Foundation框架经常使用核心服务。
1.Accounts
鉴于其始终在线的特征,iOS设备经常用于存储众多不同服务的账户信息。Accounts框架简化了存储账户信息以及对用户进行身份验证的过程。
2.Address Book
Address Book框架用于直接访问和操作地址簿。该框架用于在应用程序中更新和显示通信录。
3.CFNetwork
CFNetwork让您能够访问BSD套接字、HTTP和FTP协议请求以及Bonj our发现。
4.Core Data
Core Data框架可用于创建iOS应用程序的数据模型,它提供了一个基于SQLite的关系数据库模型,可用于将数据绑定到界面对象,从而避免使用代码进行复杂的数据操纵。
5.Core Foundation
Core Foundation提供的大部分功能与Foundation框架相同,但它是一个过程型C语言框架,因此需要采用不同的开发方法,这些方法的效率比Objective-C面向对象模型低。除非绝对必要,否则应避免使用Core Foundation。
6.Foundation
Foundation框架提供了一个Obj ective-C封装器(wrapper),其中封装了Core Foundation的功能。操纵字符串、数组和字典等都是通过Foundation框架进行的,还有其他必需的应用程序功能也如此,如管理应用程序首选项、线程和本地化。
7.Event Kit
Event Kit框架用于访问存储在iOS设备中的日历信息,还让开发人员能够在新建事件,这包括闹钟。
8.Core Location
Core Location框架可用于从iPhone和iPad 3G的GPS(非3G设备支持基于WiFi的定位服务,但精度要低得多)获取经度和维度信息以及测量精度。
9.Core Motion
Core Motion框架管理iOS平台中大部分与运动相关的事件,如使用加速计和陀螺仪。
10.Quick Look
Quick Look框架在应用程序中实现文件浏览功能,即使应用程序不知道如何打开特定的文件类型。
11.Store Kit
Store Kit框架让开发人员能够在应用程序中创建购买事务,而无需退出程序。所有交互都是通过App Store进行的,因此无需通过Store Kit方法请求或传输金融数据。
12.SystemConfiguration
System Configuration框架用于确定设备网络配置的当前状态:连接的是哪个网络?哪些设备可达?
4.2.4 核心OS层
核心OS层由最低级的iOS服务组成。这些功能包括线程、复杂的数学运算、硬件配件和加密。需要访问这些框架的情况很少。
1.Accelerate
Accelerate框架简化了计算和大数操作任务,这包括数字信号处理功能。
2.Extemal Accessory
ExtemalAccessory框架用于开发到配件的接口,这些配件是基座接口或蓝牙连接的。
3.Security
Security框架提供了执行加密(加密/解密数据)的函数,这包括与iOS密钥链交互以添加、删除和修改密钥项。
4.System
System框架让开发人员能够访问不受限制的UNIX开发环境中的一些典型工具。
4.3 Cocoa Touch中的框架
iOS 应用程序的基础 Cocoa Touch 框架重用了许多Mac系统的成熟模式,但是它更多地专注于触摸的接口和优化。UIKit 为您提供了在 iOS 上实现图形、事件驱动程序的基本工具,其建立在和 Mac OS X 中一样的 Foundation 框架上,包括文件处理、网络、字符串操作等。
Cocoa Touch 具有和 iPhone 用户接口一致的特殊设计。同时也拥有各色俱全的框架。除了 UIKit 外,Cocoa Touch 包含了创建世界一流 iOS 应用程序需要的所有框架,从三维图形到专业音效,甚至提供设备访问 API 以控制摄像头,或通过 GPS 获知当前位置。Cocoa Touch 既包含只需要几行代码就可以完成全部任务的强大的 Objective-C 框架,也在需要时提供基础的 C 语言 API 来直接访问系统。
在本节的内容中,将简单讲解 Cocoa Touch中的主要框架。
4.3.1 Core Animation(图形处理)框架
通过Core Animation,您就可以通过一个基于组合独立图层的简单的编程模型来创建丰富的用户体验。iOS提供了一系列的图形图像技术,这是建立动人的视觉体验的基础。对于一些简单的应用,可以使用Core Animation来建立具有动画效果的用户体验。动画是按定义好的关键步骤创建的,步骤描述了文字层、图像层和OpenGL ES图形是如何交互的。Core Animation在运行时按照预定义的步骤处理,平稳地将视觉元素从一步移至下一步,并自动填充动画中的过渡帧。
和iOS 中的许多场景切换功能一样,我们也可以使用Core Animation 来创建引人瞩目的效果,例如在屏幕上平滑地移动用户接口元素,并加入渐入渐出的效果,所有这些功能仅需几行Core Animation代码即可完成。
通过使用带有硬件加速的OpenGL ES API技术,可利用iPhone和iPod Touch的强大的图形处理能力。OpenGL ES具有比其桌面版本更加简单的APL,但使用了相同的核心理念,包括可编程着色器和其他能够使您的3D程序或游戏脱颖而出的扩展。
1.Quartz 2D
Quartz 2D是iOS下强大的2D图形API。它提供了专业的2D图形功能,如贝赛尔曲线、变换和渐变等。使用Quartz 2D来定制接口元素可以为您的程序带来个性化外观。由于Quartz 2D是基于可移植文档格式(PDF)的图像模型,因此显示PDF文件也是小菜一碟。
2.独立的分辨率
iPhone 4 高像素密度 Retina 屏可让任意尺寸的文本和图像都显得平滑流畅。如果需要支持早期的 iPhone,则可以使用 iOS SDK 中的独立分辨率,它可让应用程序运行于不同屏幕分辨率环境。您只需要对应用程序的图标、图形及代码稍作修改,便可确保它在各种 iOS 设备中都具极好的视觉效果,并在 iPhone 4 设备上将达到最佳。
3.照片库
应用程序可以通过 UIKit 访问用户的照片库。例如,可以通过照片选取器界面浏览用户照片库,选取某张图片,然后再返回应用程序。能够控制是否允许用户对返回的图片进行拖动或编辑。另外,UIKit还提供相机接口。通过该接口,应用程序可直加载相机拍摄的照片。
4.3.2 Core Audio(音频处理)框架
Core Audio是一门集播放、处理和录制音频的专业技术,能够轻松为应用程序添加强大的音频功能。在iOS中提供了丰富的音频和视频功能,我们可以轻松地在您的程序中使用媒体播放框架来传输和播放全屏视频。Core Audio能够完全控制iPod touch和iPhone的音频处理功能。对于非常复杂的效果,OpenAL能够让您建立3D音频模型,如图4-4所示。
图4-4 Core Audio的应用
通过使用媒体播放框架,可以让程序能够轻松地全屏播放视频。视频源可以是程序包中或者远程加载的一个文件。在影片播放完毕时会有一个简单的回调机制通知您的程序,从而可以进行相应的操作。
1.HTTP在线播放
HTTP在线播放的内置支持使得程序能够轻松在iPhone和iPod touch中播放标准Web服务器所提供的高质量的音频流和视频流。HTTP在线播放在设计时就考虑了移动性的支持,它可以动态地调整播放质量来适应 Wi-Fi 或蜂窝网络的速度。
2.AV Foundation
在iOS系统中,所有音频和视频播放及录制技术都源自AV Foundation。通常情况下,应用程序可以使用媒体播放器框架(Media Player framework)实现音乐和电影播放功能。如果所需实现的功能不止于此,而媒体播放器框架又没有相应支持,则可考虑使用AV Foundation。AV Foundation对媒体项的处理和管理提供高级支持,诸如媒体资产管理、媒体编辑、电影捕捉及播放、曲目管理及立体声声像等都在支持之列。
我们的程序可以访问iPod touch或iPhone中的音乐库,从而利用用户自己的音乐定制自己的用户体验。再例如赛车游戏可以在赛车加速时将玩家最喜爱的播放列表变成虚拟广播电台,甚至可以让玩家直接在您的程序中选择定制的播放列表,无需退出程序即可直接播放。
Core Audio是集播放、处理和录制音频为一体的专业级技术。通过Core Audio,您的程序可以同时播放一个或多个音频流,甚至录制音频。Core Audio能够透明管理音频环境,并自动适应耳机、蓝牙耳机或底座配件,同时它也可触发振动。至于高级特效,和OpenGL对图形的操作类似,OpenAL API也能播放 3D 效果的音频。
4.3.3 Core Data(数据处理)框架
Core Data框架提供了一个面向对象的数据管理解决方案,它易于使用和理解,甚至可处理任何应用或大或小的数据模型。iOS 操作系统提供一系列用于存储、访问和共享数据的完整的工具和框架。
Core Data 是一个针对 Cocoa Touch 程序的全功能的数据模型框架,而 SQLite 非常适合用于关系数据库操作。应用程序可以通过 URL 来在整个 iOS 范围内共享数据。Web 应用程序可以利用 HTML5 数据存储 API 在客户端缓冲保存数据。iOS 程序甚至可访问设备的全局数据,如地址簿里的联系人和照片库里照片。
1.Core Data
Core Data 为创建基于模型—视图—控制器(MVC)模式的良好架构的 Cocoa 程序提供了一个灵活和强大的数据模型框架。Core Data 提供了一个通用的数据管理解决方案,用于处理所有应用程序的数据模型需求,不论程序的规模大小。您可以在此基础上构建任何应用程序。只有您想不到的,没有什么做不到。
Core Data 让您能够以图形化的方式快速定义程序的数据模型,并方便地在您的代码中访问该数据模型。它提供了一套基础框架不仅可以处理常见的功能,如保存,恢复,撤销,重做等,还可以让您在应用程序中方便地添加新的功能。由于 Core Data 使用内置的 SQLite 数据库,因此不需要单独安装数据库系统。
Interface Builder 是苹果的图形用户界面编辑器,提供了预定义的 Core Data 控制器对象,用于消除应用程序的用户界面和数据模型之间的大量粘合代码。您不必担心 SQL 语法,不必维护逻辑树来跟踪用户行为,也不必创建一个新的持久化机制。这一切都已经在您将应用程序的用户界面连接到 Core Data模型时自动完成了。
2.SQLite
iOS 包含时下流行的 SQLite 库,它是一个轻量级但功能强大的关系数据库引擎,能够很容易地嵌入到应用程序中。SQLite 被多种平台上的无数应用程序所使用,事实上它已经被认为是轻量级嵌入式 SQL 数据库编程的工业标准。与面向对象的 Core Data 框架不同,SQLite 使用过程化的、针对 SQL 的 API直接操作数据表。
iOS 为设备上安装的应用程序之间的信息共享提供了强大的支持。基于 URL 语法,您可以像访问 Web 数据一样将信息传递给其他应用程序,如邮件、iTunes 和 YouTube。您也可以为自己的程序声明一个唯一的URL,允许其他应用程序与您的应用程序进行协作和共享数据。
您的应用程序可通过安全易用的 API 访问 iPhone 的数据和媒体。您的应用程序可以添加新的地址簿联系人,也可获得现有的联系信息。同样,您的应用程序可以加载、显示和编辑图片库的照片,也可使用内置的摄像头拍摄新照片。
iOS 应用程序可通过 Event Kit 框架访问用户日历数据库的事件信息。例如,可以根据日期范围或唯一标识符获取事件信息;可在事件记录发生改变的时候获得通知;可允许用户创建或编辑日历事件。通过 Event Kit 对日历数据库执行的改动会自动同步到恰当的日历,就连 CalDAV 和交换服务器中的日历也会自动同步。
XML 文件提供了一个让您的应用程序可以轻松地读写的轻量级的结构化格式。同时 XML 文件很适合 iOS 的文件系统。您可以将您的程序设置和用户偏好设置存储到内置的数据库中。这种基于 XML 的数据存储提供了一个具有强大功能的简易 API,并具有根据要求序列化和恢复复杂的对象的能力。
iOS 中先进的 Safari 浏览器支持最新的 HTML5 离线数据存储功能。脱机存储意味着通过使用一个简单的键/值数据 API 或更先进的 SQL 接口,网络应用可以将会话数据存储于本地 iPhone 或 iPod touch 设备的高速缓存中。这些数据在 Safari 启动过程中是不变的,这意味着应用程序具有更快的启动速度、更少地依赖于网络,并且有比以往更出色的表现。
4.4 iOS程序的生命周期
任何程序的生命周期都是指从程序加载到程序结束这一短时间。在本节的内容中,将详细讲解iOS程序生命周期的基本知识,为读者步入本书后面知识的学习打下基础。
4.4.1 从一段代码看iOS程序的生命周期
在iOS应用中,通过单击主页面上的图标的方式可以启动一个程序。单击后,系统会显示一个过渡的画面然后调用main()函数来加载程序。从这一刻开始,大量的初始化工作都交给了UIKit,它加载程序的用户界面并启动事件循环。在时间循环过程中,UIKit将传入的时间和自定义对象相关联并响应程序的命令事件。如果用户的某个操作引起程序的退出,UIKit会通知程序并开始结束程序过程。
在iOS程序中,很少使用 函数 main()。绝大多数实际的工作都是交给函数UIApplicationMain()来处理 。因此当我们在Xcode中新建一个工程时,任何工程的模板生成的main()函数几乎都是一样的,代码如下所示:
#import <UIKit/UIKit.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
#import <UIKit/UIKit.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
main()函数主要完成如下3个工作:
(1)创建了一个自动释放池;
(2)调用UIApplicationMain()函数;
(3)释放自动释放池。一般来说,开发者不需要修改main()函数。
函数UIApplicationMain()是初始化程序的核心,它接受4个参数,并且开发者永远不要修改传入的这4个参数。其中argc和argv两个参数来自于main()接受的两个参数;另外两个String型参数分别表示程序的主要类(principal class)和代理类(delegate class)。
如果主要类(principal class)为nil,则默认为UIApplication;如果代理类(delegate class)为nil,则程序假设程序的代理来自Main nib文件。如果这两个参数任意一个不为nil,则UIApplicationMain()函数则会根据参数创建相应的功能类。因此,如果程序中使用自定义的UIApplication类的子类(不建议继承UIApplication类建立自定义的子类),你需要将你的自定义类名作为第3个参数传进来。
4.4.2 iOS程序生命周期的原理
每一个IOS应用程序都包含一个UIApplication对象,IOS系统通过该UIApplication对象监控应用程序生命周期全过程。每一个IOS应用程序都要为其UIApplication对象指定一个代理对象,并由该代理对象处理UIApplication对象监测到的应用程序生命周期事件。
通常来说,一个iOS应用程序拥有如下所示的5种状态。
1.Not running
应用还没有启动,或者应用正在运行但是途中被系统停止。
2.Inactive
当前应用正在前台运行,但是并不接收事件(当前或许正在执行其它代码)。一般每当应用要从一个状态切换到另一个不同的状态时,中途过渡会短暂停留在此状态。唯一在此状态停留时间比较长的情况是:当用户锁屏时,或者系统提示用户去响应某些(诸如电话来电、有未读短信等)事件的时候。
3.Active
当前应用正在前台运行,并且接收事件。这是应用正在前台运行时所处的正常状态。
4.Background
应用处在后台,并且还在执行代码。大多数将要进入Suspended状态的应用,会先短暂进入此状态。然而,对于请求需要额外的执行时间的应用,会在此状态保持更长一段时间。另外,如果一个应用要求启动时直接进入后台运行,这样的应用会直接从Notrunning状态进入Background状态,中途不会经过Inactive状态。比如没有界面的应用。注意:此处并不特指没有界面的应用,其实也可以是有界面的应用,只是如果要直接进入Background状态的话,该应用界面不会被显示。
5.Suspended
应用处在后台,并且已停止执行代码。系统自动将应用移入此状态,且在此举之前不会对应用做任何通知。当处在此状态时,应用依然驻留内存但不执行任何程序代码。当系统发生低内存告警时,系统会将处于Suspended状态的应用清除出内存,以便正在前台运行的应用提供足够的内存。
由此可见,执行iOS程序的过程如图4-5所示。
图4-5 执行iOS程序的过程
作为UIApplication的代理类,必须要先实现UIApplicationDelegate协议,协议里明确了作为代理应该做或可以做哪些事情。UIApplication对象负责监听应用程序的生命周期事件,并将生命周期事件交由UIApplication代理对象处理。
在UIApplication代理对象中,和生命周期有关的函数的具体说明如下所示。
— (void)applicationWillResignActive:(UIApplication *)application:当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,比如来电话了。
—(void)applicationDidBecomeActive:(UIApplication *)application:当应用程序入活动状态执行,这个刚好跟上面那个方法相反。
—(void)applicationDidEnterBackground:(UIApplication *)application:当程序被推送到后台的时候调用。所以要设置后台继续运行,则在这个函数里面设置即可。
—(void)applicationWillEnterForeground:(UIApplication *)application:当程序从后台将要重新回到前台时候调用,这个刚好跟上面的那个方法相反。
—(void)applicationWillTerminate:(UIApplication *)application:当程序将要退出时被调用,通常是用来保存数据和一些退出前的清理工作。这个需要设置UIApplicationExitsOnSuspend的键值为YES,ios5设置Application does not run in background的键值为YES。
—(void)applicationDidReceiveMemoryWarning:(UIApplication *)application:ios设备只有有限的内存,如果为应用程序分配了太多内存,操作系统会终止应用程序的运行,在终止前会执行这个方法,通常可以在这里进行内存清理工作,防止程序被终止。
—(void)applicationDidFinishLaunching:(UIApplication*)application:当程序载入后执行。
—(BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url:当打开URL时执行。
4.4.3 UIViewController的生命周期
UIViewController是IOS顶层视图的载体及控制器,用户与程序界面的交互都是由UIViewController来控制的。UIViewController用于管理UIView的生命周期及资源的加载与释放,而UIView与UIWindow共同展示了应用用户界面。
UIViewController包含如下所示的生命周期事件。
—(void)loadView:用于加载视图资源并初始化视图。
—(void)viewDidLoad和-(void)viewDidUnload:用于释放视图资源。
—(void)viewWillAppear:(BOOL)animated:用于将要加载出视图。
—(void)viewDidAppear:(BOOL)animated:表示视图出现。
—(void)viewWillDisappear:(BOOL)animated:表示视图即将消失。
—(void)viewDidDisappear:(BOOL)animated:表示视图已经消失。
根据系统是否支持多线程来划分,可以将iOS应用程序的生命周期分为如下两种。
不支持多线程的iOS4之前的系统。
支持多线程的iOS4及其之后的系统。
1.iOS4之前系统
iOS4之前系统程序的生命周期如图4-6所示。
图4-6 iOS4之前系统程序的生命周期图
由图4-7可知,iOS 4之前系统程序的运作流程如下所示。
图4-7 iOS4及其之后系统程序的生命周期图
(1)单击 app icon 或者从应用程序url(比如在Safari地址栏中输入应用程序url)启动应用程序。
(2)进入UIApplicationDelegate的-(void)applicationDidFinishLaunching:(UIApplication *)application;或- (B OOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
(3)如果是从url启动的,则先进入UIApplicationDelegate的- (BOOL)application:(UIApplication *) application handleOpenURL:(NSURL *)url;然后再跳转到第四步;否则直接跳转到第四步。
(4)进入UIApplicationDelegate的- (void)applicationDidBecomeActive:(UIApplication *)application;。
(5)进入应用程序主循环,这时应用程序已经是活动的了,用户可以与应用程序交互。
(6)在第(5)步状态下,如果按住home键或者进行任务切换操作,然后跳转到第八步。
(7)在第五步状态下,应用程序被中断(如来电、来短信),进入UIApplicationDelegate的 - (void) applicationWillResignActive:(UIApplication *)application;如果用户选择不处理而继续留在当前应用程序,则回到第四步;如果用户选择处理,则跳转到第八步。
(8)进入UIApplicationDelegate的- (void)applicationWillTerminate:(UIApplication *)application,当前应用程序关闭。
注意:这里所说的进入,并非真正调用该消息,只是走流程。因为UIApplicationDelegate的方法都是@optional的,实现了则真正执行,没有实现则什么也不做。
2.iOS4及其之后的系统
iOS4及其之后系统程序的生命周期如图4-7所示。
由图4-8中可以看出,在支持多线程之后,情况要复杂得多了。但总体还是有规律可循的,只是多了一个后台模式而已,具体说明如下所示。
图4-8 Xcode的帮助系统
(1)在程序被中断之后,先进入后台:- (void)applicationDidEnterBackground:(UIApplication *)application;。
(2)在程序被中断后继续时,要从后台模式切换到前台:- (void)applicationWillEnterForeground: (UIApplication *)application;。
4.5 Cocoa中的类
在iOS SDK中有数千个类,但是编写的大部分应用程序都可以使用很少的类实现90%的功能。为了让读者熟悉这些类及其用途,下面介绍您将在本书后面几章中经常遇到的类。但在此之前需要注意如下4点。
Xcode为您创建了应用程序的大部分结构,这意味着即使需要某些类,使用它们也只是举手之劳。您只需新建一个Xcode项目,这些类将自动添加到项目中。
只需拖曳Xcode Interface Builder中的图标,就可将众多类的实例加入到项目中。同样,您无需编写任何代码。
使用类时,我们将指出为何需要它、它有何功能以及如何在项目中使用它。我们不希望您在书中翻来翻去,因此重点介绍概念,而不要求您记忆。
在本章后面的内容中,将介绍Apple文档工具。这些实用程序很有用,让您能够找到希望获得的所有类、属性和方法信息。如果这些正是您梦寐以求的详细信息,它们将触手可得。
4.5.1 核心类
在新建一个iOS应用程序时,即使它只支持最基本的用户交互,也将使用一系列常见的核心类。在这些类中,虽然有很多在日常编码过程中并不会用到,但是它们仍扮演了重要的角色。在Cocoa中,常用的核心类如下所示。
1.根类(NSObject)
根类是所有类的子类。面向对象编程的最大好处是当我们创建子类时,它可以继承父类的功能。NSObject是Cocoa的根类,几乎所有Objective-C类都是从它派生而来的。这个类定义了所有类都有的方法,如alloc和init。在开发中我们无需手工创建NSObject实例,但是我们可以使用从这个类继承的方法来创建和管理对象。
2.应用程序类(UIApplication)
UIApplication的作用是提供了iOS程序运行期间的控制和协作工作。每一个程序在运行期必须有且仅有一个UIApplication(或则其子类)的一个实例。在程序开始运行的时候,UIApplicationMain函数是程序进入点,这个函数做了很多工作,其中一个重要的工作就是创建一个UIApplication的单例实例。在你的代码中,你可以通过调用[UIApplication sharedApplication]来得到这个单例实例的指针。
UIApplication的主要工作是处理用户事件,它会开启一个队列,把所有用户事件都放入队列,逐个处理,在处理的时候,它会发送当前事件到一个合适的处理事件的目标控件。此外,UIApplication实例还维护一个在本应用中打开的Window列表(UIWindow实例),这样它就可以接触应用中的任何一个UIView对象。UIApplication实例会被赋予一个代理对象,以处理应用程序的生命周期事件(比如程序启动和关闭)、系统事件(比如来电、记事项警告)等。
3.窗口类(UIWindow)
UIWindow提供了一个用于管理和显示视图的容器。在iOS中,视图更像是典型桌面应用程序的窗口,而UIWindow的实例不过是用于放置视图的容器。在本书中,您将只使用一个UIWindow实例,它将在Xcode提供的项目模板中自动创建。
窗口是视图的一个子类,主要有如下两个功能:
提供一个区域来显示视图。
将事件(event)分发给视图。
一个iOS应用通常只有一个窗口,但也有例外,比如在一个iPhone应用中加载一个电影播放器,这个应用本身有一个窗口,而电影播放器还有另一个窗口。
iOS设备上有很多硬件能够因用户的行为而产生数据,包括触摸屏、加速度传感器和陀螺仪。当原始数据产生后,系统的一些框架会对这些原始数据进行封装,并作为事件传递给正在运行的应用来进行处理。当应用接收到一个事件后,会先将其放在事件队列(event queue)当中。应用的singleton从事件队列中取出一个事件并分发给关键窗口(key window)来处理。
如果这个事件是一个触摸事件的话,那么窗口会将事件按照视图层次传递到最上层(用户可见)的视图对象,这个传递顺序叫做响应链(responder chain)向下顺序。响应链最下层(也是视图最上层)的视图对象如果不能处理这个事件,那么响应链的上一级的视图将得到这个事件并尝试处理这个事件,如果不能处理的话就继续向上传递,直到找到能处理该事件的对象为止。
4.视图(UIView)
UIView类定义了一个矩形区域,并管理该区域内的所有屏幕显示,我们将其称为视图。在现实中编写的大多数应用程序,都首先将一个视图加入到一个UIWindow实例中。视图可以使用嵌套形成层次结构,例如顶级视图可能包含按钮和文本框,这些控件被称为子视图,而包含它们的视图称为父视图。几乎所有视图都可以在Interface Builder中以可视化的方式创建。
通过使用UIView类,开发者可以指定一块矩形显示区域,大小和位置都可由开发者自行定义。UIView类中的常用方法如下所示。
— (id)initWithFrame:(CGRect)aRect:UIView类最常用的初始化方法,通过一个CGRect对象指定其显示的矩形区域。
@property(nonatomic) CGRect frame:显示UIView类的矩形区域的框架。CGRect对象可以使用CGRectMake (CGFloat x, CGFloat y, CGFloat width,CGFloat height)方法构造,其中前两个数值是其起始点(通常是左上角,可重定义)在父级view中的坐标,后两个数值是其在父级view中的显示区域的大小。一个view的显示位置和显示大小随时可以通过其frame属性的重新赋值来修改。
—(void)addSubview:(UIView *)view:在此view中添加子view,当使用此方法时,新加入的view通常显示在屏幕的最前方。
—(void)removeFromSuperview:在父级view中移除某view的显示。
—(void)drawRect:(CGRect)rect:当需要手动绘制view界面的显示内容时可调用此方法,在此方法中可以获得当前的UIGraphicsGetCurrentContext对象,并在其上进行手动的绘图工作。
—(void)setNeedsDisplay:当需要手动更新view中的显示内容的时候可以调用此方法,此方法会立刻调用drawRect方法重新绘制整个view界面。view界面中的原有内容是否保留取决于其clearsContextBeforeDrawing属性设置为YES还是NO。
@property(nonatomic, copy) UIColor *backgroundColor:view显示背景色。如要设置view背景色为透明,可在此属性中指定。要注意的是,如果要隐藏整个view包括其中的其他可视化组件,则需要将hidden属性设置为YES或alpha属性设置为0.0。
5.响应者(UIResponder)
在 iOS 中,一个UIResponder类表示一个可以接收触摸屏上的触摸事件的对象,通俗一点地说,就是表示一个可以接收事件的对象。在iOS中,所有显示在界面上的对象都是从UIResponder直接或间接继承的。UIResponder类让继承它的类能够响应iOS生成的触摸事件。UIControl是几乎所有屏幕控件的父类,它是从UIView派生而来的,而后者又是从UIResponder派生而来的。UIResponder的实例被称为响应者。
由于可能有多个对象响应同一个事件,iOS将事件沿响应者链向上传递,能够处理该事件的响应者被赋予第一响应者的称号。例如当编辑文本框时,该文本框处于第一响应者状态,这是因为它处理用户输入,当我们离开该文本框后便退出第一响应者状态。在大多数iOS编程工作中,不会在代码中直接管理响应者。
UIResponder类中的常用方法如下所示。
touchesBegan:withEvent:当用户触摸到屏幕时调用方法。
tochesMoved:withEvent:当用户触摸到屏幕并移动时调用此方法。
tochesEnded:withEvent:当触摸离开屏幕时调用此方法。
tochesCancelled:withEvent:当触摸被取消时调用此方法。
6.屏幕控件(UIControl)
UIControl类是从UIView派生而来的,且是几乎所有屏幕控件(如按钮、文本框和滑块)的父类。这个类负责根据触摸事件(如按下按钮)触发操作。例如可以为按钮定义几个事件,并且可以对这些事件做出响应。通过使用Interface Builder,可以让将这些事件同编写的操作关联起来。UIControl负责在幕后实现这种行为。
UIControl类是UIView的子类,当然也是UIResponder的子类。UIControl是诸如UIButton、UISwitch、UITextField等控件的父类,它本身也包含了一些属性和方法,但是不能直接使用UIControl类,它只是定义了子类都需要使用的方法。
7.视图控制器(UIViewController)
几乎在本书的所有应用程序项目中,都将使用UIViewController类来管理视图的内容。此类提供了一个用于显示的view界面,同时包含view加载、卸载事件的重定义功能。在此需要注意的是,在自定义其子类实现时,必须在Interface Builder中手动关联view属性。UIViewController类的常用方法如下所示。
@property(nonatomic, retain) UIView *view:此属性为ViewController类的默认显示界面,可用自定义实现的Vi e w类替换。
—(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle:最常用的初始化方法,其中nibName名称必须与要调用的Interface Builder文件名一致,但不包括文件扩展名,比如要使用“aa.xib”,则应写为[[UIViewController alloc] initWithNibName:@”aa” bundle:nil]。nibBundle为指定在哪个文件夹中搜索指定的nib文件,如在项目主目录下,则可直接使用nil。
—(void)viewDidLoad:此方法在ViewController实例中的view被加载完毕后调用,如需要重定义某些要在Vi e w加载后立刻执行的动作或者界面修改,则应把代码写在此函数中。
—(void)viewDidUnload:此方法在ViewControll实例中的View被卸载完毕后调用,如需要重定义某些要在Vi e w卸载后立刻执行的动作或者释放的内存等动作,则应把代码写在此函数中。
—(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation:当iPhone的重力感应装置感应到屏幕由横向变为纵向或者由纵向变为横向时调用此方法。如返回结果为NO,则不自动调整显示方式;如返回结果为YES,则自动调整显示方式。
@property(nonatomic, copy) NSString *title:表示当View中包含NavBar时,其中的当前NavItem的显示标题。当NavBar前进或后退时,此title则变为后退或前进的尖头按钮中的文字。
4.5.2 数据类型类
在 Cocoa中,常用的数据类型类如下所示。
1.字符串(NSString/NSMutableString)
字符串是一系列字符——数字、字母和符号,在本书中将经常使用字符串来收集用户输入以及创建和格式化输出。和我们平常使用的众多数据类型对象一样,也是有两个字符串类:NSStringNSMutableString。两者的差别如下所示。
NSMutableString:可用于创建可被修改的字符串,NSMutableString实例是可修改的(加长、缩短、替换等)。
NSString实例在初始化后就保持不变。
在Cocoa Touch应用程序中,使用字符串的频率非常频繁,这导致Apple允许您使用语法@“<my stringvalue>”来创建并初始化NSString实例。例如,如果要将对象myLabel的text属性设置为字符串HelloWorld!,可使用如下代码实现:
myLabel.text=@"Hello World!";
另外还可使用其他变量的值(如整数、浮点数等)来初始化字符串。
2.数组(NSArray/NSMutableArray)
集合让应用程序能够在单个对象中存储多项信息。NSArray就是一种集合数据类型,可以存储多个对象,这些对象可通过数字索引来访问。例如我们可能创建一个数组,它包含您想在应用程序中显示所有用户反馈字符串:
myMessages=[[NSArray alloc] initWithObjects:@"Good boy!",@"Bad boy!",nil];
在初始化数组时,总是使用nil来结束对象列表。要访问字符串,可使用索引。索引是表示位置的数字,从0开始。要返回Bad boy!,可使用方法objectAtIndex实现:
[myMessages objectAtIndex:1];
与字符串一样,也有一个NSMutableArray类,它用于创建初始化后可被修改的数组。
通常在创建的时候就包含了所有对象,我们不能增加或是删除其中任何一个对象,这种特定称为immutable,NSArray中的常用方法如下所示。
(1)- (unsigned)count:得到array中的对象个数。
(2)--(id)objectAtIndex:(unsigned)i:得到索引为i的对象,如果i值超过了array对象数量,在程序运行到这里会产生错误。
(3)-(id)lastObject:得到最后一个对象,如果NSArray中没有任何对象存在,返回nil。
(4)-(BOOL)containsObject:(id)anObject:当anObject出现在NSArray中,则返回YES。
(5)--(unsigned)indexOfObject:(id)anObject:查找NSArray中是否存在anObject,并返回最小的索引值。
而NSMutableArray继承于NSArray,扩展了增加、删除对象的功能。可以使用NSArray的mutableCopy方法来复制得到一个可修改的NSMutableArray对象。
(1)- (void)addObject:(id)anObject:在reciever最后添加anObject,添加nil是非法的。
(2)- (void)addObjectsFromArray:(NSArray *)otherArray:在reciever最后把otherArray中的对象都依次添加进去。
(3)- (void)insertObject:(id)anObject atIndex:(unsigned)index:在索引index处插入对象anObject。如果index被占用,会把之后的object向后移动。index不能大于所包含对象个数,并且anObject不能为空。
(4)- (void)removeAllObjects:清空array。
(5)- (void)removeObject:(id)anObject:删除所有和anObject相等的对象。
(6)- (void)removeObjectAtIndex:(unsigned)index:删除索引为index的对象,后面的对象依次往前移。如果index越界,将会产生错误。
3.字典(NSDictionary/NSMutableDictionary)
字典也是一种集合数据类型,但是和数组有所区别。数组中的对象可以通过数字索引进行访问,而字典以“对象.键对”的方式存储信息。键可以是任何字符串,而对象可以是任何类型,例如可以是字符串。如果使用前述数组的内容来创建一个NSDictionary对象,则可以用下面的代码实现:
myMessages=[[NSDictionary alloc] initwithObjectsAndKeys:@"Good boy!",
@"positive",@"Bad boy! ",@"negative",nil];
现在要想访问字符串,不能使用数字索引,而需使用方法objectForKey、positive或negative,例如下面的代码:
[myMessages objectForKey:@"negative"]
字典能够以随机的方式(而不是严格的数字顺序)存储和访问数据。通常,也可以使用字典的修改的形式:NSMutableDictionary,这种用法可在初始化后进行修改。
4.数字(NSNumber/NSDecimalNumber)
如果需要使用整数,可使用C语言数据类型int来存储。如果需要使用浮点数,可以使用数据类型float来存储。NSNumber类用于将C语言中的数字数据类型存储为NSNumber对象,例如通过下面的代码可以创建一个值为100的NSNumber对象:
myNumberObject=[[NSNumber alloc]numberWithInt:100];
这样,我们便可以将数字作为对象:将其加入到数组、字典中等。NSDecimalNumber是NSNumber的一个子类,可用于对非常大的数字执行算术运算,但只在特殊情况下才需要它。
5.日期(NSDate)
通过使用NSDate后,可以用当前日期创建一个NSDate对象(date方法可自动完成这项任务),例如:
myDate=[NSDate date];
然后使用方法earlierDate可以找出这两个日期中哪个更早:
[myDate earlierDate: userDate]
由此可见,通过使用NSDate对象可以避免进行讨厌的日期和时间操作。
类NSDate中的常用方法如下所示。
(1)创建或初始化。
用于创建NSDate实例的类方法如下。
+ (id)date;:返回当前时间。
+ (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs;:返回以当前时间为基准,然后过了secs秒的时间。
+ (id)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secs;:返回以2001/01/01 GMT为基准,然后过了secs秒的时间。
+ (id)dateWithTimeIntervalSince1970:(NSTimeInterval)secs;:返回以1970/01/01 GMT为基准,然后过了secs秒的时间。
+ (id)distantFuture;:返回很多年以后的未来的某一天。比如你需要一个比现在(Now)晚(大)很长时间的时间值,则可以调用该方法。测试返回了4000/12/31 16:00:00。
+ (id)distantPast;:返回很多年以前的某一天。比如你需要一个比现在(Now)早(小)大很长时间的时间值,则可以调用该方法。测试返回了公元前0001/12/31 17:00:00。
用于创建NSDate实例的实例方法有:
- (id)addTimeInterval:(NSTimeInterval)secs;:返回以目前的实例中保存的时间为基准,然后过了secs秒的时间。
用于初始化NSDate实例的实例方法有。
- (id)init;:初始化为当前时间,类似date方法。
- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secs;:初始化为以2001/01/01 GMT为基准,然后过了secs秒的时间。类似dateWithTimeIntervalSinceReferenceDate:方法。
- (id)initWithTimeInterval:(NSTimeInterval)secs sinceDate:(NSDate *)refDate;:初始化为以refDate为基准,然后过了secs秒的时间。
- (id)initWithTimeIntervalSinceNow:(NSTimeInterval)secs;:初始化为以当前时间为基准,然后过了secs秒的时间。
(2)日期之间比较可用以下方法。
- (BOOL)isEqualToDate:(NSDate *)otherDate; :与otherDate比较,相同返回YES。
- (NSDate *)earlierDate:(NSDate *)anotherDate; :与anotherDate比较,返回较早的那个日期。
- (NSDate *)laterDate:(NSDate *)anotherDate; :与anotherDate比较,返回较晚的那个日期。
- (NSComparisonResult)compare:(NSDate *)other; :该方法用于排序时调用。
●当实例保存的日期值与anotherDate相同时返回NSOrderedSame;
●当实例保存的日期值晚于anotherDate时返回NSOrderedDescending;
●当实例保存的日期值早于anotherDate时返回NSOrderedAscending。
(3)取回时间间隔可用以下方法。
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)refDate; :以refDate为基准时间,返回实例保存的时间与refDate的时间间隔。
- (NSTimeInterval)timeIntervalSinceNow; :以当前时间(Now)为基准时间,返回实例保存的时间与当前时间(Now)的时间间隔。
- (NSTimeInterval)timeIntervalSince1970; :以1970/01/01 GMT为基准时间,返回实例保存的时间与1970/01/01 GMT的时间间隔。
- (NSTimeInterval)timeIntervalSinceReferenceDate; :以2001/01/01 GMT为基准时间,返回实例保存的时间与2001/01/01 GMT的时间间隔。
+ (NSTimeInterval)timeIntervalSinceReferenceDate; :以2001/01/01 GMT为基准时间,返回当前时间(Now)与2001/01/01 GMT的时间间隔。
(4)将时间表示成字符串。
- (NSString *)description;:以YYYY-MM-DD HH:MM:SS ±HHMM的格式表示时间。其中 "± HHMM" 表示与GMT存在多少小时多少分钟的时区差异。比如,若时区设置在北京,则 "±HHMM" 显示为 "+0800"。
6.URL(NSURL)
URL显然不是常见的数据类型,但在诸如iPhone和iPad等连接到Internet的设备中,能够操纵URL非常方便。NSURL类让您能够轻松地管理URL,例如,假设您有URL http://www.floraphotographs.com/index.html,并只想从中提取主机名,该如何办呢?可创建一个NSURL对象:
MyURL=[[NSURL alloc] initWithString:
@"http://www.floraphotographs.com/index.html"]
然后使用host方法自动解析该URL并提取文本www.floraphotographs.com:
[MyURL host]
这在您创建支持Internet的应用程序时非常方便。当然,还有很多其他的数据类型对象。正如前面指出的,有些对象存储了自己的数据,例如,您无需维护一个独立的字符串对象,以存储屏幕标签的文本。
注意:如果您以前使用过C或类似于C的语言,可能发现这些数据类型对象与Apple框架外定义的数据类型类似。通过使用框架Foundation,可使用大量超出了C/C++数据类型的方法和功能。另外,您还通过Objective-C使用这些对象,就像使用其他对象一样。
4.5.3 UI界面类
iPhone和iPad等iOS设备之所以具有这么好的用户体验,其中有相当部分原因是可以在屏幕上创建触摸界面。接下来将要讲解的UI界面类是用来实现界面效果的,Cocoa框架中常用的UI界面类如下所示。
1.标签(UILabel)
在应用程序中添加UILabel标签可以实现如下两个目的。
(1)在屏幕上显示静态文本(这是标签的典型用途)。
(2)将其作为可控制的文本块,必要时程序可以对其进行如下修改。
对 UILabel类的具体说明如下所示。
@property(nonatomic, copy) NSString *text:文本中要显示的字符串内容。
@property(nonatomic, retain) UIFont *font:文本中要显示的字符串的字体和大小。字体中包括字型、粗细、斜体、下画线等。UIFont对象可以使用[UIFont systemFontOfSize:10]或者[[UIFont alloc] fontWithName:@“字体名”size:10]方法初始化。
@property(nonatomic, retain) UIColor *textColor:指定要显示的文本的颜色。
@property(nonatomic) UILineBreakMode lineBreakMode:指定此文本如何分行和过长时如何截断。可取值如下。
●UILineBreakModeWordWrap:根据单词分行。
●UILineBreakModeCharacterWrap:根据字母分行。
●UILineBreakModeClip:当文本长度超过时,自动截断。
●UILineBreakModeHeadTruncation:当文本长度过长时,在头部部分使用省略号。
●UILineBreakModeTailTruncation:当文本长度过长时,在尾部部分使用省略号。
●UILineBreakModeMiddleTruncation:当文本长度过长时,在中间部分使用省略号。
@property(nonatomic) NSInteger numberOfLines:指定文本是否需要多行显示,最多可以显示多少行。
@property(nonatomic) BOOL adjustsFontSizeToFitWidth:指定文本是否可以根据显示空间自动调整字体大小。
@property(nonatomic) CGFloat minimumFontSize:当显示文本可以自动调整字体大小时,可调整的最小字体是多大。
2.按钮(UIButton)
按钮是iOS开发中使用的最简单的用户输入方法之一。按钮可响应众多触摸时间,还让用户能够轻松地做出选择。
3.开关(UISwitch)
开关对象可用于从用户那里收集“开”和“关”响应。它显示为一个简单的开关,常用于启用或禁用应用程序功能。
4.分段控件(UISegmentedControl)
分段控件用于创建一个可触摸的长条,其中包含多个命名的选项:类别1、类别2等。触摸选项可激活它,还可能导致应用程序执行操作,如更新屏幕以隐藏或显示。
5.滑块(UISlider)
滑块向用户提供了一个可拖曳的小球,以便从特定范围内选择一个值。例如滑块可用于控制音量、屏幕亮度以及以模拟方式表示的其他输入。
6.步进控件(UIStepper)
步进控件(UIStepper)类似于滑块。与滑块类似,步进控件也提供了一种以可视化方式输入指定范围内值的方式。按这个控件的一边将给一个内部属性加1或减1。
7.文本框(UITextField/UITextView)
文本框用于收集用户通过屏幕(或蓝牙)键盘输入的内容。其中UITextField是单行文本框,类似于网页订单,其包含如下所示的常用方法。
@property(nonatomic, copy) NSString *text:输入框中的文本字符串。
@property(nonatomic, copy) NSString *placeholder:当输入框中无输入文字时显示的灰色提示信息。
而UITextView类能够创建一个较大的多行文本输入区域,让用户可以输入较多的文本。此组件与UILabel的主要区别是UITextView支持编辑模式,而且UITextView继承自UIScrollView,所以当内容超出显示区域范围时,不会被自动截短或修改字体大小,而会自动添加滑动条。与UITextField不同的是,UITextView中的文本可以包含换行符,所以如果要关闭其输入键盘,应有专门的事件处理。UITextView类包含如下所示的常用方法。
@property(nonatomic, copy) NSString *text:文本域中的文本内容。
@property(nonatomic, getter=isEditable) BOOL editable:文本域中的内容是否可以编辑。
8.选择器(UIDatePicker/UIPicker)
选择器(picker)是一种有趣的界面元素,类似于自动贩卖机。通过让用户修改转盘的每个部分,选择器可用于输入多个值的组合。Apple为您实现了一个完整的选择器:UIDatePicker类。通过这种对象,用户可快速输入日期和时间。通过继承UIPicker类,还可以创建自己的选择器。
9.弹出框(UIPopoverController)
弹出框(popover)是iPad特有的,它既是一个UI元素,又是一种显示其他UI元素的手段。它让您能够在其他视图上面显示一个视图,以便用户选择其中的一个选项。例如,iPad的Safari浏览器使用弹出框显示一个书签列表,供用户从中选择。
当我们创建使用整个iPad屏幕的应用程序时,弹出框将非常方便。这里介绍的只是您可在应用程序中使用的部分类,在接下来的几章中,将探索这些类以及其他类。
10.UIColor类
本类用于指定cocoa组件的颜色,常用方法如下所示。
+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha:这是UIColor类的初始化方法,red、green、blue、alpha的取值都是0.0到1.0,其中alpha代表颜色的透明度,0.0为完全透明。
+ (UIColor *)colorWithCGColor:(CGColorRef)cgColor:通过某个CGColor实例获得UIColor实例。
@property(nonatomic,readonly) CGColorRef CGColor:通过某个UIColor获得CGColor的实例。CGColor常用于使用Quartz绘图中。
11.UITableView类
用于显示列表条目。需要注意的是,iPhone中没有二维表的概念,每行都只有一个单元格。如果一定要实现二维表的显示,则需要重定义每行的单元格,或者并列使用多个TableView。一个TableView至少有一个section,每个section中可以有0行、1行或者多行cell。常用方法如下所示。
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath:用于返回指定行的单元格。NSIndexPath实例可以由一维整型数组构建。在使用TableView的时候,[index section]可以获得某行所在的section编号,此编号从0开始;[index row]可获得某行所在的row编号,每个section中的cell编号都是从0开始。
- (void)setEditing:(BOOL)editing animated:(BOOL)animate:如果editing为YES则进入编辑模式,为NO则退出编辑模式。编辑模式可显示的按钮每行cell的设置和是否实现了delegate和datasource中的相应方法。animate值用于指定变化时是否使用动画。
- (void)reloadData:从datasource中重新加载TableView内容,刷新表格显示。
@property(nonatomic, assign) id<UITableViewDataSource> dataSource:表示TableView的数据源,协议类,其中定义了TableView加载数据时调用的相关事件和方法。
@property(nonatomic, assign) id<UITableViewDelegate> delegate:表示TableView的delegate,这是一个协议类,其中定义了TableView加载显示内容时调用的相关事件和方法。
12.UITableViewDataSource
在使用UITableView的时候必须实现下面的方法。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath:通过此方法指定了如何定义tableView中每行的Cell如何显示及显示什么内容。需要注意的是,tableView中的cell都是自动释放对象,未在页面上显示出来的cell实例会被立刻释放掉,只有当一个cell显示时,tableView才会调用此事件方法初始化或者找回某个cell实例。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView:当TableView初始化或者重新加载时使用,返回此table共有多少个section。注意,返回值应是最小为1的正整数。如返回0会导致意外崩溃。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section:当TableView初始化或者重新加载时使用,返回某section中共有多少行。返回值可为0。
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section:表示返回某section的header或者footer文本,只有未重定义section header/footer view的时候才有用。
- (void)tableView:(UITableView *)tableViewcommitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath:表示当提交table编辑结果的时候调用此方法。当一个table可以进入编辑模式删除数据的时候,可在此方法中添加删除逻辑。
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath:当完成table中的单元格移动的时候调用此方法。当通过移动单元格修改了某table的内部排序的时候,可在此方法中更新排序逻辑。
4.6 国际化
在开发项目时,我们无需关注显示语言的问题,若在代码中任何地方要显示文字都这样调用下面格式的代码。
NSLocalizedString(@"AAA", @"bbb");
这里的AAA相当于关键字,它用于以后从文件中取出相应语言对应的文字。bbb相当于注释,翻译人员可以根据bbb的内容来翻译aaa,这里的aaa与显示的内容可以一点关系也没有,只要程序员自己能看懂就行。比如,一个页面用于显示联系人列表,这里调用可以用如下所示的写法:
NSLocalizedString(@"shit_or_anything_you_want", @"联系人列表标题");
写好项目后,取出全部的文字内容送给翻译去翻译。这里取出所有的文字列表很简单。使用Mac的genstrings命令。具体方法如下所示。
(1)打开控制台,切换到项目所在目录。
(2)输入命令:genstrings ./Classes/*.m。
(3)这时在项目目录中会有一个Localizable.strings文件。其中内容如下:
/* 联系人列表标题 */
"shit_or_anything_you_want" = "shit_or_anything_you_want"
(4)翻译只需将等号右边改好就行了。这里如果是英文,修改后的代码如下如下:
/* 联系人列表标题 */
"shit_or_anything_you_want" = "Buddies";
如果是法文,翻译后如下:
/* 联系人列表标题 */
"shit_or_anything_you_want" = "Copains";
翻译好语言文件以后,将英语文件拖入项目中,然后右键单击,选择Get Info,选择Make Localization。此时XCode会自动复制文件到English.lproj目录下,再添加其他语言。
在编译程序后,在iPhone上运行,程序会根据当前系统设置的语言来自动选择相应的语言包。
注意:genstrings产生的文件拖入XCode中可能是乱码,这时只要在XCode中右击文件,选择Get Info→General→File Encoding下选择“UTF-16”格式后即可解决。
4.7 使用Xcode学习iOS框架
经过本章前面内容的学习,了解到iOS的框架非常多,而每个框架都可能包含数十个类,而每个类都可能有数百个方法。信息量非常大,非常不利于我们学习并记忆。为更深入地学习它们,最有效的方法之一是选择一个您感兴趣的对象或框架,并借助Xcode文档系统进行学习。Xcode让您能够访问浩瀚的Apple开发库,您可通过类似于浏览器的可搜索界面进行快速访问,也可使用上下文敏感的搜索助手(Research Assistant)。在接下来的内容中,将简要介绍这两种功能,提高读者的学习效率。
4.7.1 使用Xcode文档
打开Xcode文档的方法非常简单,依次选择菜单栏中的Help→Documentation→API Reference选项后,将启动帮助系统,如图4-8所示。
单击眼睛图标以探索所有的文档。导航器左边显示了主题和文档列表,而右边显示了相应的内容,就像Xcode项目窗口一样。进入您感兴趣的文档后,就可阅读它并使用蓝色链接在文档中导航。您还可以使用内容窗格上方的箭头按钮在文档之间切换,就像浏览网页一样。事实上,确实很像浏览网页,因为您可以添加书签,以便以后阅读。要创建书签,可右键单击导航器中的列表项或内容本身,在从上下文菜单中选择Add Bookmark。还可访问所有的文档标签,方法是单击导航器顶部的书籍图标。
1.在文档库中搜索
浏览是一种不错的探索方式,但对于查找有关特定主题的内容(如类方法或属性)来说不那么有用。要在Xcode文档中搜索,可单击放大镜图标,再在搜索文本框中输入要查找的内容。您可输入类、方法或属性的名称,也可输入您感兴趣的概念的名称。例如当输入“UILabel”时,Xcode将在搜索文本框下方返回结果,如图4-9所示。
图4-9 搜索结果
搜索结果被分组,包括Reference(API文档)、System Guides/Tools Guides(解释/教程)和SampleCode(Xcode示例项目)。
2.管理Xcode文档集
Xcode接收来自Apple的文档集更新,以确保文档系统是最新的。文档集是各种文档类别,包括针对特定Mac OS X版本、Xcode本身和iOS版本的开发文档集。要下载并自动获得文档集更新,可打开Xcode首选项(选择菜单Xcode>Preferences),再单击工具栏中的Documentation图标。
在Documentation窗格中,选中复选框Check for and Install Updates Automatically,这样Xcode将定期连接到Apple的服务器,并自动更新本地文档。还可能列出了其他文档集,要在以后自动下载相应的更新,可以单击列表项旁边的Get按钮。
要想手动更新文档,可单击Check and Install Now按钮。
4.7.2 快速帮助
要在编码期间获取帮助,最简单、最快捷的方式之一是使用Xcode Quick Help助手。要打开该助手,可按住Option键并双击Xcode中的符号(如类名或方法名),也可以依次选择菜单Help>Quick Help,此时会打开一个小窗口,在里面包含了有关该符号的基本信息,还有到其他文档资源的链接。
1.使用快速帮助
假如有如下所示的一段代码:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
在上述演示代码中,涉及了viewWillAppear。按住Option键并单击viewWillAppear。这将打开如图4-10所示的Quick Help弹出框。
图4-10 Quick Help弹出框
要打开有关该符号的完整Xcode文档,单击右上角的书籍图标;您还可单击Quick Help结果中的任何超链接,这样可以跳转到特定的文档部分或代码。
注意:通过将鼠标指向代码,可知道单击它是否能获得快速帮助;因为如果答案是肯定的,Xcode编辑器中将出现蓝色虚线,而鼠标将显示问号。
2.激活快速帮助检查器
如果发现快速帮助很有用,并喜欢能够更快捷地访问它,那么您很幸运,因为任何时候都可使用快速帮助检查器来显示帮助信息。实际上,在您输入代码时,Xcode就会根据输入的内容显示相关的帮助信息。
要打开快速帮助检查器,可以单击工具栏的View部分的第三个按钮,以显示实用工具(Utility)区域。然后,单击显示快速帮助检查器的图标(包含波浪线的深色方块),它位于Utility区域的顶部。这样,快速帮助将自动显示有关光标所处位置的代码的参考资料。
3.解读Quick Help结果
Quick Help最多可在10个部分显示与代码相关的信息。具体显示哪些部分取决于当前选定的符号(代码)类型。例如类属性没有返回类型,而类方法有有返回类型。
Abstract(摘要):描述类、方法或其他符号提供的功能。
Availability(可用性):支持该功能的操作系统版本。
Declaration(声明):方法的结构或数据类型的定义。
Parameters(参数):必须提供给方法的信息以及可选的信息。
Return Value(返回值):方法执行完毕后将返回的信息。
Related API(相关API):选定方法所属类的其他方法。
Declared In(声明位置):定义选定符号的文件。
Reference(参考):官方参考文档。
Related Documents(相关文档):提到了选定符号的其他文档。
Sample Code(示例代码):包含类、方法或属性的使用示例的示例代码文件。
在需要对对象调用正确的方法时,Quick Help简化了查找过程:无需试图记住数10个实例方法,而只需了解基本知识,并在需要时让Quick Help指出对象暴露的所有方法。