类别category
类别是一种为现有类添加新方法的方式.习惯上把类别代码放在独立的文件中,以"类名+类别名称"命名.
类别的基本语法如下:
@interface ClassName(CategoryName)
//method declarations
@end
@interface 类名(类别名)
类别方法申明
@end
注意几点:
1.现有类的类名位于 @interface之后
2.括号中是类别的名称(只要名称唯一,可以添加任意多的类别)
3.类别没有实例变量部分
类别的方法可以自由引用类的实例变量(无论公有或私有),
类扩展
一个Thing的类如下
@interface Thing: NSObject
@property (assign) NSInteger thing;
@property (readonly,assign) NSInteger thing2;
- (void) resetAllValues;
@end
@interface Thing() //类的扩展不需要名字, 也可以有名字, 有的话写在括号里面,可以有多个,创建的数量不限
{
NSInteger thing4;
}
@property (readwrite, assign) NSInteger thing2; //可以在自己的类中使用,可以将thing2的只读权限改成可读写的权限
@property (assign) NSInteger thing3; //可以添加实例变量thing3, 这个变量在Thing类里面是没有的
@end
类的扩展很像定义一个类,只不过没有继承的父类.我们做的工作就是获取Thing类, 并添加私有属性和方法来扩展Thing类.
我们在类扩展中把thing2这个变量原有的只读权限改成了可读写权限, 那么编译器就会生成setter方法, 不过它是只能在这个类中访问的私有方法, 在公共的接口中只有getter方法.
在类扩展中添加的私有属性thing3,只能在这个类内部使用.thing4也是私有的.
利用类别分散实现代码
方法是: 将大型的单个类分散到多个不同的.m文件中.
类别可以访问继承的类的实例变量,类别具有更高的优先级.
在使用一个对象时, 对象的方法是在接口中声明,父类中声明还是在类别中声明的不重要,也不会影响结果.
一个类的实现代码不仅可以分散到不同的源文件中,也可以分散到不同的框架中.
iOS内存管理
比较详细的讲解了 iOS内存管理
ARC只能作用于OC的对象, 对于C中的API或Core Foundation中的对象是不能处理的, 所以ARC并不是万能的, 而且对于项目中一些遗留的MRC代码部分, 也不起作用.
通过类别创建前向引用
作为前向引用的类别必须声明在类.h文件中,或者单独创建类别.h和类别.m文件。
创建前向引用的原因和作用:
定义在类名.h文件中的方法/属性一定是公开的,而在类名.m中的类延展(Extension)中定义的方法/属性都是私有的。或者不在任何地方申明,只在类.m中写实现代码的方法也是私有的。
如果一些特定的场景如修改别人的bug, 编写测试代码, 需要访问一些私有方法, 那么就需要用到类别在.h文件中声明,用法如下:
.h文件中进行了声明, 在.m文件中无需进行实现, 即可进行调用.
非正式协议和委托类别
委托是一种对象,由另一个类请求执行某种工作. 非正式协议用于实现委托,委托允许定制对象行为.
构成一个代理delegate需要三种文件 1个雇主类a 1个委托类b 1个委托协议c protocal
委托机制的实例
只要对象实现了委托方法,任何类的对象都可以成为委托对象.
响应选择器
关键字@selector, 一个方法名,以OC运行时使用的特殊方式编码,以执行快速查询.
Car类的setEngine选择器是
@selector(Engine);
respondsToSelector方法询问对象以确定是否能响应某个消息
Car *car = [[Car alloc] init];
if([Car respondToSelector: @selector(setENgine)])
{ NSLog(!"yw")
}
Car类的对象确实能够响应setEngine消息,所以代码可以输出 yw.
选择器可以被传递,可以作为方法的参数使用,们甚至可以作为实例变量被存储.
如Foundation中的NSTimer类, 可以反复向一个对象发送消息.