一、概念性
1、nil, Nil 和 id
· 每一个对象都是 id 类型的。该类型可以作为一种弱类型使用。id 是一个指针,所以在使用时应注意是否需要再加 *。例如 id*foo = nil,实际是定义一个指针的指针;
· nil 等价于指向对象的 NULL 指针。nil 和NULL 不应该被混用。实际上,nil 并不简单是 NULL 指针;
· Nil 等价于指针 nil 的类。在 Objective-C 中,一个类也是一个对象(作为元类 Meta-Class 的实例)。nil 代表 NULL 指针,但它也是一个类的对象,nil 就是 Nil类的实例。C++ 没有对应的概念,不过,如果你熟悉 Java 的话,应该知道每一个类对象都对应一个 Class 实例,类似这个。
引申--nil、Nil、NULL、NSNULL的区别
nil 是对Objective-C id 对象赋空值.
Nil: A null pointer to an Objective-C class.表示对类进行赋空值.
NULL: A null pointer to anything else, is for C-style memory pointers. 用于对非对象指针赋空值,比如C指针.
NSNull 对于像NSArray这样的类型,nil或NULL不能做为加到其中的Object,如果定义了一个NSArray,为其分配了内存,又想设置其中的内容为空,则可以用[NSNULL null】返回的对象来初始化NSArray中的内容
2、SEL
SEL 用于存储选择器 selector 的值。所谓选择器,就是不属于任何类实例对象的函数标识符。这些值可以由 @selector 获取。选择器可以当做函数指针,但实际上它并不是一个真正的指向函数的指针。
3、@encode
为了更好的互操作性,Objective-C 的数据类型,甚至自定义类型、函数或方法的元类型,都可以使用 ASCII 编码。@encode(aType) 可以返回该类型的 C 字符串(char *)的表示。
4、类声明
. 实例方法以减号 – 开头,而 static 方法以 + 开头。
. @class 关键字只用于前向声明。为避免循环引用,C 语言有一个前向声明的机制,即仅仅告诉存在性,而不理会具体实现。
5、static属性
Objective-C 中不允许声明 static 属性。但是,我们有一些变通的方法:在实现文件中使用全局变量(也可以添加 static 关键字来控制可见性,类似 C 语言)。这样,类就可以通过方法访问到,而这样的全局变量的初始化可以在类的 initialize 方法中完成。
1.函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,
因此其值在下次调用时仍维持上次的值;
2.在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
3.在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明 它的模块内;
4.在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
5.在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。
6、self、_cmd、@selector
. self是每个消息接收时的隐藏参数,其值就是当前对象。它的值可以被改变。
. 指向成员函数的指针被称为选择器 selector。它的类型是 SEL,值通过 @selector 获得。@selector 接受方法名(包括 label)。使用类 NSInvocation 则可以通过选择器调用方法。大多时候,工具方法族 performSelector: (继承自 NSObject)更方便,约束也更大一些。
. @selector 的值是在编译器决定的,因此它并不会减慢程序的运行效率。
. 严格说来,选择器并不是一个函数指针。它的底层实现是一个 C 字符串,在运行时被注册为方法的标识符。当类被加载之后,它的方法会被自动注册到一个表中,所以 @selector 可以很好的工作。根据这种实现,我们就可以使用 == 来判断内存地址是否相同,从而得出选择器是否相同,而无需使用字符串函数。
. _cmd 指的是当前方法,也是一个隐藏参数。
@implementation Foo
-(void) f:(id)parameter // 等价于 C 函数 void f(id self, SEL _cmd,id parameter)
{
id currentObject = self;
SEL currentMethod = _cmd;
[currentObjectperformSelector:currentMethod
withObject:parameter]; // 递归调用
[self performSelector:_cmd withObject:parameter]; // 也是递归调用
}
@end
基本规则是,所有使用 alloc,[mutable]copy[WithZone:] 或者是 retain 增加计数器的对象都要用 [auto]release 释放。事实上,有三种方法可以增加引用计数器,也就意味着仅仅有有限种情况下才要使用 release 释放对象:
· 使用alloc 显式实例化对象;
· 使用copy[WithZone:] 或者mutableCopy[WithZone:] 复制对象(不管这种克隆是不是伪克隆);
· 使用retain。
《从C++到Objective-C》中文网址:http://www.cnblogs.com/jacktu/archive/2011/11/06/2238353.html
《从C++到Objective-C》英文网址:http://www.chachatelier.fr/programmation/fichiers/cpp-objc-en.pdf