- ObjC是一种动态语言,所谓动态是在编译时增加了很多的运行期代码和运行期数据。这些运行期代码负责将编译后的ObjC代码粘接起来形成一个系统,而运行期数据则用于动态查询内存数据的描述信息(如类描述信息)。
- ObjC依然是C语言的扩充,是增加面向对象编程的C,与C++有很多共同特点,但是又有比C++多得多的运行期支持。ObjC一样会编译成可执行的机器码。兼容C语言所有特性,支持指针操作,通过指针可以遍历内存。这同C#、java、swift不同,后三种语言是基于引用,不支持指针操作,内存管理全部由编译器实现,编译时会加入代码管理内存的分配与释放。
- ObjC基于C++和C#/java之间,ObjC将很多编译期和链接器的工作放到了运行期,这样做的好处就是让程序实现更加灵活,而坏处就是牺牲部分性能(但是这可以通过优化来弥补)。对于局部变量的处理,ObjC与C语言是一样的,都基于栈空间的管理,而对于对象的管理,ObjC比C++增加了很多东西,可以说,C++在编译完成后,基本就没有了对象的概念,这同用C语言写的代码在内存中的内容没有太多差别,C++唯一保留的就是对象的类型信息和虚方法表(用于实现多态),因此C++编写的程序的内存内容与程序源码相差不大。而ObjC的运行期对象相对复杂很多。
- ObjC对象的方法调用是运行期绑定的,而在C++中只有虚拟方法表中的方法才是通过动态绑定的,而且C++的运行期绑定其实也只是通过对象指针找到虚拟方法表然后进行地址偏移来获得虚拟方法地址的,这只是地址计算,编译器加入的代码相对简单,通过地址偏移计算,速度也相对较快。而在ObjC中,任何对象方法的调用都是动态查询的,方法调用至少有两个参数,一个是对象本身(如果是类方法,就没有对象指针),一个就是方法名,这是一个字符串参数,方法名在C++编译中会变成一个符号(最终会变成一个地址),而在ObjC编译中,编译器会将方法名保存在常量数据区,而所有的方法调用编译时都会变成了对objc_msgSend(id self, SEL cmd, ….)函数的调用,cmd是一个对字符串对象的引用(字符串对象保存的就是方法名,注意这不是直接的字符串地址,而是一个NSString对象,必须通过对象中的指针才能找到字符串常量)。这个函数会根据id(地址)找到对象本身,而对象中则保存了指向类信息(类对象,就是类描述信息)的指针,类信息中则有方法表,通过遍历方法表就可以找到目标方法的地址,如果没找到则抛出异常。这样实现的好处,让程序变的异常的灵活,你可以向一个对象发送一个方法调用消息,而不必知道对象的类型,在ObjC中,有一个id类型,就是无类型对象指针,如果我们编写一个函数,通过将id类型作为参数,然后就可以向这个id发送一个方法调用,当然可以通过@selector查询是否支持某个方法调用,那么只要对象有这个方法,就可以实现调用,而无论对象类型。
在delphi中的dynamic方法的调用有些类似,或者windows的COM对象的方法调用也有些类似。
- ObjC中,声明对象变量,必须加上“*”,也就是说,对象变量必须是指针,如果不加上“*”,那么编译器认为你在申请一个栈空间变量。
NSString str; 这样的声明是错误的,因为对象不能在栈空间申请,编译器也不会增加对构造
函数的调用,而在C++中,这样声明是容许的。
不过同C语言一样,struct变量是在栈空间申请的,因此可以直接这样定义。
CGRect rect;结构体可以直接在栈空间申请。
- 在类头文件中尽量少引入其他头文件,因为当其他程序要用到本类时,会引入本类的头文件,如果在本类头文件引入不必要的其他头文件,就会让编译增加时间。而且也容易引起混乱。
在类头文件中,可以对引用的类用@class className 来声明一个符号是一个类。
在实现(implementation)文件中再#import 该类头文件。
- 字面量(常量):
采用@开头,如@1.0 , @2.5f,@YES,@“This is a String”,@(x+y),@‘A’
NSDictionary *dict = @{@“key”:@“value1”,……}
- 多用类型常量const,少用#define宏定义(预处理指令)
static NSString *const constStr = @“Some Strings”
static const Int kInt = 12;
static:与C++语言的static有些区别,ObjC的static表示变量仅在当前的编译单元(输出目标文件.o)可见。
如果不声明为static,则编译器在.o目标文件的输出符号表中包含该符号定义,这样如果有两个目标文件定义同样的名称,那么链接器就会报错。
如果我们期望一个变量能在另一个目标文件能使用,那么就采用extern声明
在头文件中声明变量
extern NSString *const constStr;
在实现文件中初始化变量;
NSString *const constStr = @“SomeString”;
那么在引用该类头文件的程序单元中,编译器会发现定义了extern变量,就会在外部单元去查找,而在本单元的目标文件中的输入符号表会包含该变量名。当链接器链接时,会全局查找符号表。
extern与C语言的用法基本一样。
- ObjC中的enum类型,可以定义类型,还可以指定值。
enum state:NSInteger{ //也可以不指明NSInteger,那么可以用byte类型来保存state
on =1,
off = 0, //必须要加逗号,如果不指明=0,那么编译器会自动填2
}
type enum stat