一、 变量作用域
l 变量的作用域主要分为四种:
u (1)@public (公开的)在有对象的前提下,任何地方都可以直接访问。
u (2)@protected (受保护的)只能在当前类和子类的对象方法中访问
u (3)@private (私有的)只能在当前类的对象方法中才能直接访问
u (4)@package (框架级别的)作用域介于私有和公开之间,只要处于同一个框架中就可以直接通过变量名访问
l 使用注意和补充
u (1)在类的实现即.m文件中也可以声明成员变量,但是因为在其他文件中通常都只是包含头文件而不会包含实现文件,所以在这里声明的成员变量是@private的。在.m中定义的成员变量不能喝它的头文件.h中的成员变量同名,在这期间使用@public等关键字也是徒劳的。
u (2)在@interface @end之间声明的成员变量如果不做特别的说明,那么其默认是protected的。
u (3)一个类继承了另一个类,那么就拥有了父类的所有成员变量和方法,注意所有的成员变量它都拥有,只是有的它不能直接访问。
二、@[email protected]
l 让编译好器自动编写一个与数据成员同名的方法声明来省去读写方法的声明。
1)声明property的语法为:@property (参数1,参数2) 类型 名字;
如:
@property(nonatomic,retain) UIWindow *window;
1) 实现 synthesize的语法为:@synthesize age = _age;
l 手动实现
u 若手动实现了setter方法,编译器就会自动生成getter方法。反之,若手动实现了getter方法,编译器会自动生成setter方法。
u 默认情况下,setter跟getter方法的实现,会去访问下划线_开头的成员变量
三、构造方法
l 构造方法:用来初始化对象的方法,是对象方法。
l 构造方法的目的,为了让对象创建出来,成员变量就会有一些固定值。
l 重写构造的注意点
Ø 先调用父类的构造方法([super init])
Ø 再进行子类内部成员变量的初始化
l 自定义构造方法规范
Ø 一定是对象方法,一定是以_开头
Ø 返回值一般是id类型
Ø 方法名一般以init开头
l 自定义一个构造方法
- (id) initWithName:(NSString*)name andAge:(int)ageandNo:(int)no
{
If(self= [super init])
{
_no= no;
self.name= name;
self.age= age;
}
returnself;
}
四、分类
Ø 如何在不改变原来类模型的前提下,给类扩充一些方法?有2种方式
l 继承
l 分类(Category)
1. 格式
Ø 分类的声明
@interface 类名 (分类名称)
// 方法声明
@end
Ø 分类的实现
@implementation 类名 (分类名称)
// 方法实现
@end
2. 好处
Ø 一个庞大的类可以分模块开发
Ø 一个庞大的类可以由多个人来编写,更有利于团队合作
3. 注意
Ø Category可以访问原始类的实例变量,但不能添加变量,只能添加方法。如果想添加变量,可以考虑通过继承创建子类
Ø Category可以实现原始类的方法,但不推荐这么做,因为它是直接替换掉原来的方法,这么做的后果是再也不能访问原来的方法
Ø 多个Category中如果实现了相同的方法,只有最后一个参与编译的才会有效
五、类的本质
1. 类也是个对象
Ø 其实类也是一个对象,是Class类型的对象,简称“类对象”
Ø Class类型的定义
typedef struct objc_class *Class;
Ø 类名就代表着类对象,每个类只有一个类对象
2. +load和+initialize
Ø +load
l 在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法
l 先加载父类,再加载子类;也就是先调用父类的+load,再调用子类的+load
l 先加载元原始类,再加载分类
l 不管程序运行过程有没有用到这个类,都会调用+load加载
Ø +initialize
l 在第一次使用某个类时(比如创建对象等),就会调用一次+initialize方法
l 一个类只会调用一次+initialize方法,先调用父类的,再调用子类的
3. 获取类对象的2种方式
Class c = [Person class]; // 类方法
或者
Person *p = [Person new];
Class c2 = [p class]; // 对象方法
4. 类对象调用类方法
Class c = [Person class];
Person *p2 = [c new];
六、description分类
1. -description方法
使用NSLog和%@输出某个对象时,会调用对象的-description方法,并拿到返回值进行输出
2. +description方法
使用NSLog和%@输出某个类对象时,会调用类对象+description方法,并拿到返回值进行输出
3. 修改NSLog的默认输出
l 重写-description或者+description方法即可
4. 死循环陷阱
l 如果在-description方法中使用NSLog打印self
七、SEL
1. 方法的存储位置
Ø 每个类的方法列表都存储在类对象中
Ø 每个方法都有一个与之对应的SEL类型的对象
Ø 根据一个SEL对象就可以找到方法的地址,进而调用方法
Ø SEL类型的定义
typedef struct objc_selector *SEL;
2. SEL对象的创建
SEL s = @selector(test);
SEL s2 = NSSelectorFromString(@"test");
3. SEL对象的其他用法
// 将SEL对象转为NSString对象
NSString *str = NSStringFromSelector(@selector(test));
Person *p = [Person new];
// 调用对象p的test方法
[p performSelector:@selector(test)];
八、 NSLog输出增强
Ø __FILE__:源代码文件名
Ø __LINE__:NSLog代码在第几行
Ø _cmd:代表着当前方法的SEL
// 下面的代码会引发死循环
- (void)test {
[self performSelector:_cmd];
}