void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses) { ... // Discover categories. for (EACH_HEADER) { category_t **catlist = _getObjc2CategoryList(hi, &count); bool hasClassProperties = hi->info()->hasCategoryClassProperties(); for (i = 0; i < count; i++) { category_t *cat = catlist[i]; // 根据分类结构体中的cls查询到一个活动的类指针 Class cls = remapClass(cat->cls);
if (!cls) { // Category's target class is missing (probably weak-linked). // Disavow any knowledge of this category. catlist[i] = nil; if (PrintConnecting) { _objc_inform("CLASS: IGNORING category \?\?\?(%s) %p with " "missing weak-linked target class", cat->name, cat); } continue; }
// Process this category. // First, register the category with its target class. // Then, rebuild the class's method lists (etc) if // the class is realized. // 首先,为目标类注册category,然后对已实现的类重新构造类方法列表 bool classExists = NO; // 如果category存在实例方法/协议/属性 if (cat->instanceMethods || cat->protocols || cat->instanceProperties) { // 添加未附加的分类 addUnattachedCategoryForClass(cat, cls, hi); if (cls->isRealized()) { remethodizeClass(cls); classExists = YES; } if (PrintConnecting) { _objc_inform("CLASS: found category -%s(%s) %s", cls->nameForLogging(), cat->name, classExists ? "on existing class" : ""); } }
if (cat->classMethods || cat->protocols || (hasClassProperties && cat->_classProperties)) { addUnattachedCategoryForClass(cat, cls->ISA(), hi); if (cls->ISA()->isRealized()) { remethodizeClass(cls->ISA()); } if (PrintConnecting) { _objc_inform("CLASS: found category +%s(%s)", cls->nameForLogging(), cat->name); } } } } ... }
/*********************************************************************** * remethodizeClass * Attach outstanding categories to an existing class. * 将外部的categories添加到已存在的类上 * Fixes up cls's method list, protocol list, and property list. * 修正类的方法列表、协议列表、属性列表 * Updates method caches for cls and its subclasses. * 更新类和子类的方法缓存 * Locking: runtimeLock must be held by the caller **********************************************************************/ staticvoidremethodizeClass(Class cls){ category_list *cats; bool isMeta;
runtimeLock.assertLocked();
isMeta = cls->isMetaClass();
// Re-methodizing: check for more categories if ((cats = unattachedCategoriesForClass(cls, false/*not realizing*/))) { if (PrintConnecting) { _objc_inform("CLASS: attaching categories to class '%s' %s", cls->nameForLogging(), isMeta ? "(meta)" : ""); } attachCategories(cls, cats, true/*flush caches*/); free(cats); } }
// 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];
void *objc_destructInstance(id obj) { if (obj) { // Read all of the flags at once for performance. bool cxx = obj->hasCxxDtor(); bool assoc = obj->hasAssociatedObjects(); // This order is important. if (cxx) object_cxxDestruct(obj); if (assoc) _object_remove_assocations(obj); obj->clearDeallocating(); } return obj; }
void _object_remove_assocations(id object) { vector< ObjcAssociation,ObjcAllocator<ObjcAssociation> > elements; { AssociationsManager manager; AssociationsHashMap &associations(manager.associations()); if (associations.size() == 0) return; disguised_ptr_t disguised_object = DISGUISE(object); AssociationsHashMap::iterator i = associations.find(disguised_object); if (i != associations.end()) { // copy all of the associations that need to be removed. ObjectAssociationMap *refs = i->second; for (ObjectAssociationMap::iterator j = refs->begin(), end = refs->end(); j != end; ++j) { elements.push_back(j->second); } // remove the secondary table. delete refs; associations.erase(i); } } // the calls to releaseValue() happen outside of the lock. for_each(elements.begin(), elements.end(), ReleaseValue()); }