范畴的主要目的是防止一个拥有众多方法的类太长
可以将类中的方法分散在多个范畴中
范畴属于类 可以看作给类的方法分组
OC用法
@interface 类名(范畴名)
方法的声明
@end
@implementation 类名(范畴名)
方法的定义
@end
主要目的就是将众多的类方法分散在多个范畴中 在.h文件中声明所有的范畴 但是在不同的.m中定义不同的范畴
关于在范畴中添加属性声明@property
注意!在范畴的声明中不能直接声明变量 只能通过写@property int a;然后在正常状态下@preperty会自动定义set和get方法 但是如果这个@property是声明在范畴中就不会在定义中自动创建 并且不能在范畴定义中写@synthesize 需要自己手动实现 因为防止随意访问同一个类的不同文件中定义的实例变量
关于在多个范畴中重写同一个方法
最后一次编辑(比如在这个范畴的方法中加一个空格都行)的是哪个范畴中的方法就是调用哪个范畴中的方法 范畴重写的方法一定能覆盖原有方法(也就的在类中定义的那个)
类拓展 就是没有名字的范畴
类拓展可以声明实例变量但是类拓展也只能声明
实现一定只能在主实现中
#interface A()//就是括号里不写东西
{
int a;
}
-()say;
swift用法
struct SomeType {
var existingProperty: Int
}
//拓展 并添加计算属性
extension SomeType {
var newComputedProperty: Int {
// 在这里进行计算
return existingProperty * 2
}
}
关联引用
可以为一个对象增加多个引用
必须使用确定的不再改变的地址作为键值 例如静态局部变量 static char key;
买这个关联的引用是属于每一个调用了这个函数的对象自己的 没有调用相应函数的就没有
import<objc/runtime>
void objc-setAssociatedObject(id object,void *key,id value,objc_AssociationPolicy policy)
为对象object添加以key指定的地址作为关键值 以value为值的关联引用 plicy指定关联引用的存储策略
通过将value指定为nil就可以删除key的关联
简单来说 我们可以理解为 凭空创造了一个叫key的变量加到了这个对象中 这个函数就是将value值放到object绑定的叫key的变量中 因为OC是可以在运行时动态的添加 应该是可以改变地址内存的大小
id objc_getAssociatedObject(id object,void *key)
返回object以key为关键字(key可以看作这个新关联的变量的名字,可以通过这个名字找到这个变量)关联的对象 如果没有关联到任何对象则返回nil
这里就是从key绑定的变量拿值出来
实例
我的理解:
static char key;//这种是放在文件中 只有这个文件中的方法才能使用这个关联的引用 如果放到类中 就可以自己在任何时候调用
@implementation A
-(void)func
{
NSString *temp = @"abc";
objc_setAssociatedObject(self, &key,temp, OBJC_ASSOCIATION_RETAIN);//这里将temp的值存给key标识的那个变量
}
-(void)prin
{
id temp =objc_getAssociatedObject(self,&key);//获取key标识的变量的值
NSLog(@"%@",temp);
}
@end
int main()
{
A *a = [[A alloc]init];
A *aa = [[A alloc]init];
[a func];
[a prin];//abc
[aa prin];//null
return 0;
}
将key当作实例变量 则可以直接在main函数中获取值
@interface A
{
@public
char key;
}
-(void)func;
@end
@implementation A
-(void)func
{
NSString *temp = @"abc";
objc_setAssociatedObject(self, &key,temp, OBJC_ASSOCIATION_RETAIN);//这里将temp的值存给key标识的那个变量
}
@end
int main()
{
A *a = [[A alloc]init];
[a func];//先将值赋进去
id temp = objc_getAssociatedObject(a,&(a->key));//abc
return 0;
}
在范畴中添加属性问题
范畴通常是用来添加类方法的,如果在类别中添加了@property 回味类添加一个属性,但不会自动创建相应的实例变量,此时就需要手动创建setting和getting方法和对应的实例变量,
可能能通过这种方式解决但是不确定
// MyCategory.h
#import <Foundation/Foundation.h>
@interface MyClass (MyCategory)
@property (nonatomic, strong) NSString *deviceID;
@end
// MyCategory.m
#import "MyCategory.h"
#import <objc/runtime.h>
@implementation MyClass (MyCategory)
// 这里创建一个关联的键来存储属性的值
static char DeviceIDKey;
- (NSString *)deviceID {
return objc_getAssociatedObject(self, &DeviceIDKey);
}
- (void)setDeviceID:(NSString *)deviceID {
objc_setAssociatedObject(self, &DeviceIDKey, deviceID, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end