1、Objective-C 为 ANSI C 添加了下述语法和功能:
定义新的类
类和实例方法
方法调用(称为发消息)
属性声明(以及通过它们自动合成存取方法)
静态和动态类型化
块 (block),已封装的、可在任何时候执行的多段代码
基本语言的扩展,例如协议和类别
2、在 @interface
指令和 @end
指令之间,编写属性和方法的声明。这些声明组成了类的公共接口。分号标记每个属性和方法声明的结尾。如果类具有与其公共接口相关的自定函数、常量或数据类型,请将它们的声明放在@interface
...@end
块之外。
3、可以将方法想像成一个规范特定对象的函数,可能会有所帮助。通过将一则消息发送到——或发消息给——一个对象,您可调用该对象的一个方法。Objective-C 中有两种类型的方法:实例方法和类方法。
实例方法,由类的实例来执行。换言之,在调用实例方法之前,必须先创建该类的实例。实例方法是最常见的方法类型。
类方法,可由它所在的类直接执行。它不需要对象的实例作为消息的接收者。
4、块是封装工作单元的对象,即可在任何时间执行的代码段。它们在本质上是可移植的匿名函数,可作为方法和函数的参数传入,或可从方法和函数中返回。块本身具有一个已类型化的参数列表,且可能具有推断或声明的返回类型。您还可以将块赋值给变量,然后像调用函数一样调用它。
您接着可以调用块变量,就像它是一个函数一样:
int result = myBlock(4); // result is 28 |
5、
类型 |
描述和字面常量 |
---|---|
|
动态对象类型。动态类型化的对象和静态类型化的对象的否定字面常量,都是 |
|
动态类类型。其否定字面常量是 |
|
选择器的数据类型 ( |
|
Boolean 类型。字面常量值是 |
6、
Foundation 框架,顾名思义,是用于所有 iOS 和 OS X 编程的基础工具箱。您需要熟悉此工具箱,才能成功地在这些平台上开发。
Foundation 定义了几十个用途广泛的类和协议,其中有三种类和协议是极其基础的:
根类及相关协议。根类
NSObject
及其同名协议指定了所有 Objective-C 对象的基本接口和行为。还有一些协议可以由类采用,以便客户端可以拷贝类的实例并对其状态进行编码。值类。值类产生的实例称为值对象,是一种面向对象的包装器 (wrapper),用于基本的数据类型(如字符串、数字、日期或二进制数据)。同一值类的实例,如果具有相同的封装值,则视为是相等的。
集 (collection) 类。集类的实例(称为集)管理一组的对象。区分特定集类型的关键,在于它让您如何使用所包含的对象。集 (collection) 中的项通常是值对象。
在 Objective-C 编程中,集与值对象极其重要,因为它们经常用作方法的参数和返回值。
7、
对于强耦合对象(即通过直接引用建立相互连接的对象),发送消息轻而易举。但是对于松耦合对象(也就是说,在对象图中相隔很远),应用程序不得不寻找其他的通信方式。Cocoa Touch 和 Cocoa 框架具有许多机制和技巧,使得松耦合对象之间能够通信(正如下图所示)。这些机制和技巧,全部基于设计模式(您稍后将会学到更多内容),使得有效地构建稳固的和可扩展的应用程序成为可能。
8、
通过分配并初始化对象来创建对象
为了分配对象,您发送 alloc
消息给该对象的类,来获得该类的一个“原始”(未初始化)的实例。分配对象时,Objective-C 运行时会从应用程序的虚拟内存,为对象分配足够的内存。除分配内存以外,运行时在分配期间还做了一点别的事,例如将所有实例变量设定为零。
分配原始实例后,您必须立即对它初始化。初始化将一个对象的初始状态(即它的实例变量和属性)设定为合理的值,然后返回对象。初始化的目的在于返回有用的对象。
在框架中,您会发现很多称为初始化程序的方法,它们将对象初始化并且具有相似的格式。初始化程序为实例方法,它们以 init
开始,并返回一个类型为 id
的对象。根类 NSObject
声明 init
方法供其他所有类继承。其他类可以声明各自的初始化程序,各有专属的关键词和参数类型。例如,NSURL 类声明以下初始化程序:
- (id)initFileURLWithPath:(NSString *)path isDirectory:(BOOL)isDir |
分配对象和将对象初始化时,您将分配调用嵌套在初始化调用内。以上面的初始化程序为例:
NSURL *aURL = [[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory() isDirectory:YES]; |
作为一种安全的编程实践,您可以测试返回的对象以验证该对象已经创建。无论在哪个阶段发生对象不可创建的事情,初始化程序都会返回 nil
。尽管 Objective-C 可让您发送消息到 nil
而不会有负面后果(例如,不会抛出异常),您的代码可能没有预期结果,因为它没有调用任何方法。您应该使用初始化程序返回的实例,而不是由 alloc
方法返回的实例。
通过调用类工厂方法创建对象
您还可以通过调用类工厂方法来创建对象——类工厂方法是一种用于分配、初始化实例并返回一个它自己的实例的类方法。类工厂方法很方便,因为它们允许您只使用一个步骤(而不是两个步骤)就能创建对象。它们采用以下形式:
+ (
type)
className...
(在这里 className 不包括任何前缀)
Objective-C 框架的某些类定义了类工厂方法,这些方法与这些类的初始化程序相对应。例如,NSString
声明了以下两个方法:
- (id)initWithFormat:(NSString *)format, ...; |
+ (id)stringWithFormat:(NSString *)format, ...; |
以下是您可以如何使用 NSString
这个类工厂的例子:
NSString *myString = [NSString stringWithFormat:@"Customer:%@", self.record.customerName]; |
9、
您可以使用 isEqual:
方法比较两个对象。让接收消息的对象与传入的对象进行比较;如果相同,该方法返回 YES
。例如:
BOOL objectsAreEqual = [obj1 isEqual:obj2]; |
if (objectsAreEqual) { |
// do something... |
} |
请注意,对象相等与对象相同是有分别的。对于后者,请使用相同运算符 ==
测试两个变量是否指向同一个实例。
当您比较同一个类的两个对象时,到底在比较什么?这取决于类。根类 NSObject
将指针相等用作比较基础。任何级别的子类都可覆盖其超类的实现,以让比较基于类特定标准,如对象状态。例如,如果一个假设的 Person 对象和另一个 Person 对象的名字、姓氏和出生日期属性都相符,则这两个对象可能相等。
Foundation 框架的值和集类,声明的比较方法为 isEqualTo
Type:
格式,其中 Type 是类类型减去 NS 前缀,如 isEqualToString:
和isEqualToDictionary:
。此比较方法会假定传入的对象属于给定类型,否则会引发异常。
10、
每个框架都属于 iOS 系统的一个层。每个层都建立在它的下层之上。尽可能使用较高级的框架,而非较低级的框架。较高级的框架向较低级的结构提供面向对象的抽象。
11、
Core Data 框架管理应用程序的数据模型
Core Data 管理对象图。借助 Core Data,您可以创建模型对象(称为被管理的对象)。您管理那些对象之间的关系,并通过框架更改数据。Core Data 利用内建的 SQLite 技术,高效地储存和管理数据。
使用 Core Data:
存储对象和从储存处取回对象
支持基本的撤销/重做
自动验证属性值
对内存中的数据进行过滤、分组和整理
使用
NSFetchedResultsController
管理表格视图中的结果支持基于文稿的应用程序
Core Graphics 框架帮助您创建图形
高质量的图形,是所有 iOS 应用程序的一个重要组成部分。在 iOS 中创建图形的最简易便捷方法,是将预渲染的图像与 UIKit 框架的标准视图和控制配合使用,并让 iOS 完成绘图。UIKit 还提供用于自定绘图的类,包括路径、颜色、图案、渐变、图像、文本和变换。尽可能地使用 UIKit(较高级的框架),而非 Core Graphics(较低级的框架)。
当您想要编写在 iOS 和 OS X 之间直接共享的绘图代码时,使用 Core Graphics。Core Graphics 框架也称为 Quartz,它在这两个平台上几乎相同。
使用 Core Graphics:
制作基于路径的绘图
使用边缘模糊化渲染
添加渐变、图像和颜色
使用坐标空间变换
创建、显示和解析 PDF 文稿
Core Animation 可让您制作高级动画和视觉效果
UIKit 提供的动画,是建立在 Core Animation 技术之上的。如果您需要超出 UIKit 功能的高级动画,可以直接使用 Core Animation。Core Animation 接口包含在 Quartz Core 框架中。借助 Core Animation,您创建不同层次的层对象,并对它们进行操控、旋转、缩放、变换等等。通过使用大家所熟悉的 Core Animation 视图式抽象,您可以创建动态用户界面,而无需使用低级的图形 API,如 OpenGL ES 等。
使用 Core Animation:
创建自定动画
给图形添加时序功能
支持关键帧动画
指定图形布局约束
将多层更改分组为原子更新
OpenGL ES 框架提供 2D 和 3D 绘图工具
OpenGL ES 支持基础的 2D 和 3D 绘图。Apple 实施的 OpenGL ES 标准,与设备硬件紧密协作,为全屏幕游戏类应用程序提供很高的帧速率。
使用 OpenGL ES:
创建 2D 和 3D 图形
制作更复杂的图形,如数据可视化、飞行模拟或视频游戏。
访问底层图形硬件
12、
调用还是覆盖?
在子类中覆盖的框架方法,一般不是要亲自调用的方法,至少不是直接的调用。只需要重新实施该方法,剩下的事情就交给框架处理。事实上,您越是编写应用程序特定版本的方法,在自己的代码中调用它的可能性就越小。一般来说,框架类会声明公共方法,以便作为开发者的您可以使用它们来执行以下两项操作中的一项:
调用它们,以使用该类提供的服务。
覆盖它们,以便将您的代码引入到框架定义的程序模型中。
有时候,一个方法同时归入这两个类别;在调用时提供有价值的服务,也可以加以策略性的覆盖。但是,在大多数情况下,如果方法可供调用,则它已经由框架完全定义,您就不需要再在代码中重新定义它。如果是需要在子类中重新实施的方法,框架会用它来执行特定的任务,因此,它会在适当的时候,自行调用该方法。下图描述两大类型的框架方法。
上图中,自定类 (myMethod
) 的假设方法调用由框架实施的 setNeedsDisplay:
方法。框架做一些工作为绘制建立环境,然后调用框架声明的方法 drawRect:
,该方法则由自定类覆盖,以执行实际的绘制。
覆盖一个方法不必是一项艰巨的任务。通过编写一两行代码,小心地重新实施一个方法,常常就可以对超类行为做出重大改变。
13、
调用超类实现
覆盖框架方法时,必须决定是否要替换继承的方法的行为,或者扩展或补充该行为。如果想要替换现有的行为,提供自己的方法实现即可;如果想要扩展该行为,调用超类实现并提供自己的代码即可。
通过发送消息(与调用方法的消息相同)到 super
来调用超类实现。通过将消息发送给 super
,您就将该方法的超类代码插入到重新实现的调用点。举个例子,比如一个假设的 Celebrate
类,定义了一个称为 performFireworks
的方法。在框架于视图中绘画并播放烟火动画后,您想在视图显示一个横幅。下图说明在这种情况下调用 super
的方式:
因此,决定是否调用 super
,基于您打算如何重新实施方法:
如果打算补充超类实现的行为,请调用
super
。如果打算替换超类实现的行为,就不要调用
super
。
如果您要补充超类行为,另一个需要重点考虑的,是何时调用一个方法的超类实现。您可能想超类代码在执行您的代码前,就做好它的工作,反之亦然。