核心语法
一、 点语法
p.age不是访问的成员变量,而这就是oc中的点语法,点语法的本质是方法的调用,而不是访问成员变量,当使用点语法时,编译器会自动展开相应的方法。切记点语法的本质是转换成相应的set和get方法。
(在OC中访问成员变量的方法只有一种,“->”作为访问成员变量的方法)
点语法使用注意:
a) Self.age= age; return self.age;这两种情况下会引发死循环!
b) 如果没有set和get方法,则不能使用点语法。
二、 成员变量的作用域:
a) @private:只能在当前类的实现@implementation中直接访问
b) @protected :可以在当前类以及子咧的实现@implementation中直接访问
c) @public:任何地方都可以直接访问;
d) @package:同一个“体系内”(框架)可以访问,介于@private跟@public之间
注意:
a) 当父类中声明的变量为@private变量在子类中只能通过set和get方法访问变量
b) 当在声明中没有特别支持类的类型则默认的类的类型为@protected类型
c) 在实现中也可以声明成员变量,但写的成员变量只默认为私有的,不会出现其他类型,即使你写成别的类型,也只能为私有的类型,子类是无法访问的,在.m中的成员变量中不能存在与@interface中同名的成员变量!
d) 写类的声明是为了保证类的完整性,但是不写声明直接在.m中写方法的实现也是可以的。当在main.m中直接写的实现.m中就可以直接定义成员变量类型
三、 @property 和@synthsize和id
@property可以自动生成某个成员变量的set和get方法的声明
@synthsize可以自动生成某个成员变量的set和get方法的实现
例如:@sythsize age=_age;
@synthsize自动生成age的set跟get方法的实现,并且访问_age这个成员变量;
@property可以实现三步:
- 定义变量
- 实现方法
- 实现声明
注意这个是在xcode4.4版本之后才实现的!
@synthsize的细节:
1.@synthsize age = _age;
- Set和get实现中会访问成员变量_age;
- 如果成员变量_age不存在,就会自动生成一个@private的成员变量_age;
2. @synthsizeage;
- Set 和get实现中会访问成员变量age
- 如果成员变量age不存在,就会自动程程一个@private的成员变量age
3. 手动实现
- 若手动实现set方法,编译器就只会生成get方法
- 若手动实现get方法,编译器就只会生成set方法
- 若同时手动实现了set方法和get方法,编译器就不会自动生成不存在的成员变量
四、 id
id是指万能指针,能指向\操纵任何OC对象;
注意:写id的时间不要写*;
局限性:调用一个不存在的方法,编译器会马上报错!
例如:
Person *p = [Person new];
NSObject *o = [Person new];
Id d = [Person new];
五、 构造方法
完整的创建一个可用对象分为两步:
- 分配存储空间 +alloc
- 初始化 -init
New方法是创建一个对象的方法,[Person new]是一个类方法。
构造方法的用途是用来初始化对象的方法,是一个以“-”开头的对象方法(默认初始化完了之后的值都是0)
Person *p = [[Person alloc] init];
例题:
每个Person对象创建出来,它的age都是10.
重写init构造方法条件
1. 一定要调用回super的init方法:初始化父类中声明的一些成员变量和其他属性。
Self = [super init];//当前对象 self
2. 如果对象初始化成功,才有必要进行下来的初始化
If(self!=nil)
{
//初始化成功
_age = 10;
}
3. 然会初始化的数值
Return self;
以上代码简化后:
-(id)init
If(self = [super init])
_age=10;
Returnself;
重写构造方法的注意点:
a) 先调用父类的构造方法([superinit])
b) 在进行子类内部成员变量的初始化
自定义构造方法:
1) 命名规范
a) 一定是对象方法,一定以“-”开头
b) 返回值一般是id类型
c) 方法名一般以init开头
2) 自定义构造方法的用途:初始化值
a) 当父类中的成员变量存在的时间我们仅仅需要直接将需要初始化的值直接传到父类中初始化即可
b) 父类的属***给父类方法处理,子类仅需要处理自己的属性即可
六、 类别\分类Category
给某一个类扩充一些方法(不修改原来类的代码);
//声明
@interface 类名(分类名称)
@end
//实现
@implementation 类名(分类名称)
分类的作用:
在不改变原来类内容的基础上,可以增加一些方法
使用注意:
1. 分类只能增加方法,不能增加成员变量!
2. 分类方法实现中可以访问原来类中声明的成员变量
3. 分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法失效没法继续使用
4. 方法调用的优先级:分类à原来的类à父类
类库:很多类的集合;
类的本身也是一个对象是一个class类型的对象,即是类对象;
七、 Load方法和initalize方法
Initialize方法可以看成类的初始化!
Load方法在程序加载使用时就被调用,当程序第一次加载使用时就调用initalize方法
1. 当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和类的+load方法。只会调用一次
2. 当第一次使用某个类的时间,就会调用当前类的+initialize方法
3. 先加载父类,在加载子类(先调用父类的load方法在调用子类的load方法)
先初始化父类,在初始化子类(先调用个父类的+initalize方法,在调用子类的+initalize方法)
Initialize方法可以起到监听的作用!可以知道这个类什么时间第一次被使用!
分类的load方法是在最后被加载的
Description方法:
+description()决定类对象的输出结果
-description()决定了实例对象输出的结果
地址:%p
__LINE__ ---------à行号 NSLog(@“%d”__LINE__);
__FILE__ ---------à文件 NSLog(@“%s”__FINLE__);
NSLog输出C语言字符串的时间不能有中文
__func__ ---------à方法 NSLog(@“%s”__Lfunc__);
八、 SEL方法
1. 方法的存储位置
a) 每个类的方法列表都储存在类对象中
b) 每个方法都有一个与之对应的sel类型的对象
c) 根据一个sel对象就可以找到方法的地址,进而调用方法
d) Sel类型的定义
typedef struct objc selector *SEL
2. SEL对象的创建
SEL s = @selector(test);
SEL s2 =NSSelectorFromString(str);
SEL 其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址,找到方法地址就可以调用方法