类扩展
@interface LGPerson ()
@property (nonatomic, copy) NSString *ext_name;
- (void)ext_instanceMethod;
- (void)ext_classMethod;
@end
1.可以说成是特殊的分类,也称作匿名分类
分类的声明
@interface LGPerson (Cate)
@end
2.可以给类添加成员属性
3.可以给类添加方法。
总结:类扩展帮助类声明属性,方法和成员变量,一般在m文件中声明,由于在m文件中声明对调用者不可见 所以是私有的。声明的属性会自动生成getter和setter方法并实现
类别(分类)
1.专门用于给类添加新的方法
2.不能给类添加成员变量,添加了成员变量,也无法取到
给分类添加成员变量会报错实例变量不能放在类别中
3.可以通过runtime给分类添加属性
4.分类中用@ property定义变量,只会生成变量的getter和setter方法的声明,不能生成方法实现和带下划线的成员变量。
可以通过clang -rewrite-objc main.m -o outFile查看
给分类添加属性,系统会对setter 和getter方法声明,我们可以访问,然后编译不会报错,但是运行会报错。我们通过关联实现setter和getter方法
@property (nonatomic, copy) NSString *cate_name;
- (void)setCate_name:(NSString *)cate_name{
/**
1: 对象
2: 标识符
3: value
4: 策略
*/
objc_setAssociatedObject(self, "cate_name", cate_name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void)setCate_good:(NSString *)cate_good {
objc_setAssociatedObject(self, "cate_good", cate_good, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
关联对象
查看源码看调用过程
setAssociateddrawio.png
在_object_set_associative_reference中我们查看类之间的关系
Associations.png
void
_object_set_associative_reference(id object, const void *key, id value, uintptr_t policy)
{
DisguisedPtr<objc_object> disguised{(objc_object *)object};
ObjcAssociation association{policy, value};
association.acquireValue();
{
AssociationsManager manager;
AssociationsHashMap &associations(manager.get());
if (value) {
auto refs_result = associations.try_emplace(disguised, ObjectAssociationMap{});
if (refs_result.second) {
object->setHasAssociatedObjects();
}
auto &refs = refs_result.first->second;
auto result = refs.try_emplace(key, std::move(association));
if (!result.second) {
association.swap(result.first->second);
printf("%s",__func__);
}
}
}
// release the old value (outside of the lock).
association.releaseHeldValue();
}
1.DisguisedPtr:封装object对象,用来查询map的key值
2.ObjcAssociation:封装策略和值
3.AssociationsManager:里面包含一个静态map,用来处理关联对象的表
4.AssociationsHashMap:一个map,初始化传入的是AssociationsManager对象中的静态表,
5.association.acquireValue();使用传入的策略对value值进行引用计算的处理
- auto refs_result = associations.try_emplace(disguised, ObjectAssociationMap{});从静态map中通过object取出一个包含两个数据的结构
- if (refs_result.second) 如果是对象的第一次关联,则对对象的isa关联变量设值为true
8.refs.try_emplace(key, std::move(association)); 通过object 找到静态表(MAP)中对应的表(MAP),在通过传入的key进行设值value。
网友评论