通过上篇文章,我学习了OC 的几个比较容易混淆的关键字,在讨论 self= [super init] 的方法的时候,想到了还涉及到SEL 所以开篇第一个就学习一下SEL ,不过今天主要学的是OC 特有语法
一 . SEL
1 . SEL 全称叫做 selector 选择器
SEL 是一个数据类型,所以要在内存中申请空间存储数据.
SEL 其实是一个类 SEL 对象是用来存储1个方法的
可以理解@selector(),方法选择器.于是乎就可说是C 中的指针函数.而在OC里不能用指针函数,所有就只能搞一个@selector 来去了
他的结果的SEL类型,用assgin修饰.去取方法的编号(函数地址)
2. 类是以Class对象的形式存储在代码段中.
还要将方法存储的 类对象之中,怎么江方法存储在类对象中.
1. 先创建一个SEL 对象.
2. 将方法的信息存储在这个SEL对象之中
3. 再将这个SEL对象作为类对象的属性
3. 拿到存储方法的SEL对象
1. 因为SEL是一个typedef类型的 在自定义的时候已经加*了.所以我们在声明SEL 指针的时候 不需要加 *
2. 取到存储方法的SEL 对象
SEL S = @selector(方法名)
4. 调用方法的本质
[s sayHi];
内部的原理
1. 先拿到存储sayHi方法的SEL对象,也就是拿到存储sayHi方法的SEL 数据.SEL消息
2. 将这个SEL消息发送给 s对象
3. 这个时候,s对象接收到这个SEL消息以后 就知道要调用方法
4. 根据对象的ISA指针找到存储类的类对象
5. 找到这个类对象以后 在这个类对象中去搜寻是否有传入的SEL数据相匹配的 如果有 就执行 , 如果没有再找父类 直到NSObject .
5 . 手动为对象发送SEL消息
1. 先得到方法的SEL数据
2. 将这个SEL消息发送给s对象
调用对象的方法 将SEL 数据发送给对象
- (id)performSelector:(SEL)aSelector;
Person *p1 = [Person new];
SEL s1 = @selector(sayHi);
[p1 performSelector:s1]; 与 [p1 sayHi]效果是完全一样的.
3. 调用1个对象的方法有两种.
1. [对象名 方法名];
2. 手动的为对象发送SEL消息.
其实这个调用的本质 就是 消息机制
我也是查看了大神的blog 才慢慢的对消息机制有了一点认知 话不多说 好文章当让与 火友 一起分享 <a href="http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/" target-"_blank">火之叶</a>
二 . 点语法
1 . Java C# 对象可以使用点语法来访问对象的成员变量
OC中也有点语法. OC 中也可以使用点语法来访问对象的属性.但是OC的点语法和Java C#是完全不一样的
OC 的对象如果要为属性赋值或者取值 就要滴啊用对应的getter 或者 setter
2. 使用点语法来访问对象的属性
语法
对象名.去掉下划线的属性名;
这个时候就会将@"火之叶"赋值给p1对象的_name属性
p1.name = @"火之叶";
NSString *name = p1.name; 把p1对象的_name 属性的值取出来
```
##3. 点语法的原理
1). 当使用点语法赋值的时候. 这个时候编译器会将点语法转换为调用setter方法的代码.
对象名.去掉下划线的属性名 = 数据;
转换为:
[对象名 set去掉下划线的属性名首字母大写:数据];
p1.age = 10;
[p1 setAge:10];
2).当使用点语法取值的时候.这个时候编译器会将点语法转换为调用getter方法的代码.
对象名.去掉下划线的属性名;
转换为:
[对象名 去掉下划线的属性名];
int age = p1.age;
int age = [p1 age];
## 4.注意.
1). 在getter和setter中慎用点语法,因为有可能会造成无限递归 而程序崩溃,
2). 点语法在编译器编译的时候 会转换为调用setter getter方法的代码.
p1.name = @"jack";
[p1 setName:@"jack";
NSString *name = p1.name;
NSString *name = [p1 name];
如果我们的setter方法和getter方法名不符合规范 那么点语法就会出问题.
3). 如果属性没有封装getter setter 是无法使用点语法的
因为点语法的本质是getter setter方法.
#三 . 统一的介绍
## 1. @property
Xcode4.4之前
@property: 只生成getter、setter方法的声明.
@synthesize: 生成私有属性.并生成getter、setter方法的实现.
Xcode4.4开始.
@property增强:
1). 自动生成私有属性.
2). 自动生成私有属性的getter setter方法的声明和实现.
##2. 编译检查与运行检查
编译检查:
通过1个指针去访问对象的成员的时候,编译判断可以不可以的准则: 指针的类型当中是否有这个成员.
运行检查:
在程序运行的时候,通过1个指针去访问对象的成员之前,还会检查指针所指向的对象中是否真的有这个成员.
##3. 万能指针(NSObject、id). instancetype
NSObject和id 它们都是万能指针,可以指向任意的OC对象.
NSObject指针访问对象的成员的时候,编译器会做编译检查.
id指针调用指针指向的对象的方法的时候.编译器不做任何检查 直接通过.
id指针的缺点: 不能使用->访问属性 也不能使用点语法.
instancetype: 只能做为方法的返回值.代表返回当前类的对象.
##4. 动态类型检测 反射
1). 判断指针指向的对象中 指定的方法是是否可以调用.
2). 判断类方法是否可以调用.
3). 判断对象是否为指定类的对象或者子类对象.
4). 判断对象是否为指定类的对象.
5). 判断指定的类是否为另外1个类的子类.
## 5. 构造方法.
1). new是1个类方法. 创建对象初始化对象返回对象.
2). new方法的内部其实就是 alloc init
3). init方法就叫做构造方法. 初始化对象
4). 重写init构造方法.
5). 自定义构造方法.
如果你想要调用init默认的构造方法.那么new可以. 也可以使用alloc init
如果你像要调用自定义的构造方法.这个时候就必须先alloc 再调用自定义的init