OC语言特性
2020-12-13 13:45
标签:直接 nullable 获取 obj 数据类型 中心 生效 一个 针对 传递方式一对一 容易出现循环引用,所以委托方需要通过weak关键字来弱化引用 OC语言特性 标签:直接 nullable 获取 obj 数据类型 中心 生效 一个 针对 原文地址:https://www.cnblogs.com/GoodmorningMr/p/11536076.htmlCategory
struct category_t {
const char *name; //分类名称
classref_t cls; //分类所属的宿主类
struct method_list_t *instanceMethods; //实例方法列表
struct method_list_t *classMethods; //类方法列表
struct protocol_list_t *protocols; //协议
struct property_list_t *instanceProperties; //实例属性列表
// Fields below this point are not always present on disk.
struct property_list_t *_classProperties;
method_list_t *methodsForMeta(bool isMeta) {
if (isMeta) return classMethods;
else return instanceMethods;
}
property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};
// Attach method lists and properties and protocols from categories to a class.
// Assumes the categories in cats are all loaded and sorted by load order,
// oldest categories first.
static void
attachCategories(Class cls, category_list *cats, bool flush_caches)
{
if (!cats) return;
if (PrintReplacedMethods) printReplacements(cls, cats);
bool isMeta = cls->isMetaClass();
// fixme rearrange to remove these intermediate allocations
/*二维数组
*/
method_list_t **mlists = (method_list_t **)
malloc(cats->count * sizeof(*mlists));
property_list_t **proplists = (property_list_t **)
malloc(cats->count * sizeof(*proplists));
protocol_list_t **protolists = (protocol_list_t **)
malloc(cats->count * sizeof(*protolists));
// Count backwards through cats to get newest categories first
int mcount = 0; //方法
int propcount = 0;
int protocount = 0;
int i = cats->count; //宿主分类的总数
bool fromBundle = NO;
while (i--) { //这里是倒叙遍历,最先访问最后编译的分类,所以多个分类添加的同名方法最后编译的最终生效
//获取一个分类
auto& entry = cats->list[i];
//获取该分类的方法列表
method_list_t *mlist = entry.cat->methodsForMeta(isMeta);
if (mlist) {
//最后编译的分类最先添加到分类数组中
mlists[mcount++] = mlist;
fromBundle |= entry.hi->isBundle();
}
property_list_t *proplist =
entry.cat->propertiesForMeta(isMeta, entry.hi);
if (proplist) {
proplists[propcount++] = proplist;
}
protocol_list_t *protolist = entry.cat->protocols;
if (protolist) {
protolists[protocount++] = protolist;
}
}
//获取随著类当中的rw数据,其中包含宿主类的方法列表信息
auto rw = cls->data();
//主要针对分类中有关于内存管理想干方法情况下的一些特殊处理
prepareMethodLists(cls, mlists, mcount, NO, fromBundle);
/*
rw代表类
methods代表类的方法列表
attachLists 方法的含义是 将含有没count个元素的mlists拼接到rw的methods上
*/
rw->methods.attachLists(mlists, mcount);
free(mlists);
if (flush_caches && mcount > 0) flushCaches(cls);
rw->properties.attachLists(proplists, propcount);
free(proplists);
rw->protocols.attachLists(protolists, protocount);
free(protolists);
}
关联对象
//设定一个value值,通过key设定和value的映射关系,通过policy策略关联到对象上面
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy)
//根据指定的key到object中获取和key相对应的关联值
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
//根据指定对象移除它所有的关联对象
objc_removeAssociatedObjects(id _Nonnull object)
void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) {
// retain the new value (if any) outside the lock.
ObjcAssociation old_association(0, nil);
//根据policy的值对value进行copy或者retain操作
id new_value = value ? acquireValue(value, policy) : nil;
{
//关联对象管理类,C++实现的一个类
AssociationsManager manager;
//获取其维护的一个HashMap
AssociationsHashMap &associations(manager.associations());
disguised_ptr_t disguised_object = DISGUISE(object);
if (new_value) {
// break any existing association.
//根据对象指针查找对应的一个ObjectAssociationMap结构的map
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
// secondary table exists
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
old_association = j->second;
j->second = ObjcAssociation(policy, new_value);
} else {
(*refs)[key] = ObjcAssociation(policy, new_value);
}
} else {
//没找到关联值的时候进行添加
// create the new association (first time).
ObjectAssociationMap *refs = new ObjectAssociationMap;
associations[disguised_object] = refs;
(*refs)[key] = ObjcAssociation(policy, new_value);
object->setHasAssociatedObjects();
}
} else {
//当value传为空时则对该关联进行擦除操作
// setting the association to nil breaks the association.
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
old_association = j->second;
refs->erase(j); //擦除操作
}
}
}
}
// release the old value (outside of the lock).
if (old_association.hasValue()) ReleaseValue()(old_association);
}
扩展(Extension)
代理(Delegate)
通知(NSNotification)
KVO
//直接为成员变量赋值
[self willChangeValueForKey:@"value"];
_value += 1;
[self didChangeValueForKey:@"value"];
KVC(键值编码技术)
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKey:(NSString *)key;
// 如果开发者想让这个类禁用KVC里,那么重写+ (BOOL)accessInstanceVariablesDirectly方法让其返回NO即可,这样的话如果KVC没有找到set
属性关键字
OC语言笔试题
@property (nonatomic, retain) id obj;
- (void)setName:(id)obj
{
if (_obj != obj) {
[_obj release];
_obj = [obj retain];
}
}
上一篇:C#二维码生成
下一篇:C# 导出Excel