iOS小知识之底层load方法的调用时机

464 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

1.load方法的调用时机?

load_images函数中

  • 1.add_class_to_loadable_list:将所有主类的laod方法,收集到一张主类load方法表
  • 2.add_category_to_loadable_list:将所有分类的load方法,收集到一张分类load方法表
  • 3.call_class_loads:先循环调用主类的load方法
  • 4.call_category_loads:再循环调用分类的load方法 如下图所示

image-9.png

1.1 add_class_to_loadable_list

void add_class_to_loadable_list(Class cls) 
{ 
    IMP method; 
    
    loadMethodLock.assertLocked();
    
    method = cls->getLoadMethod(); 
    if (!method) return; // Don't bother if cls has no +load method 
    
    if (PrintLoading) { 
        _objc_inform("LOAD: class '%s' scheduled for +load", cls->nameForLogging()); 
    }
    
    if (loadable_classes_used == loadable_classes_allocated) {
        loadable_classes_allocated = loadable_classes_allocated*2 + 16;
        loadable_classes = (struct loadable_class *) realloc(loadable_classes, loadable_classes_allocated * sizeof(struct loadable_class));
    }
    
    loadable_classes[loadable_classes_used].cls = cls; 
    loadable_classes[loadable_classes_used].method = method; 
    loadable_classes_used++; 
}
  • 将所有主类的load方法,收集到一张主类load方法表

1.2 add_category_to_loadable_list

void add_category_to_loadable_list(Category cat) 
{
    IMP method; 
    
    loadMethodLock.assertLocked(); 
    
    method = _category_getLoadMethod(cat);
    
    // Don't bother if cat has no +load method 
    if (!method) return; 
    
    if (PrintLoading) { 
        _objc_inform("LOAD: category '%s(%s)' scheduled for +load", _category_getClassName(cat), _category_getName(cat)); 
    }
    
    if (loadable_categories_used == loadable_categories_allocated) {
        loadable_categories_allocated = loadable_categories_allocated*2 + 16; 
        loadable_categories = (struct loadable_category *) realloc(loadable_categories, loadable_categories_allocated * sizeof(struct loadable_category)); 
    }
    
    loadable_categories[loadable_categories_used].cat = cat; 
    loadable_categories[loadable_categories_used].method = method;
    loadable_categories_used++; 
}
  • add_category_to_loadable_list:将所有分类的load方法,收集到一张分类load方法表

1.3 call_class_loads

static void call_class_loads(void) 
{
    int i; 
    
    // Detach current loadable list. 
    struct loadable_class *classes = loadable_classes; 
    int used = loadable_classes_used; 
    loadable_classes = nil; 
    loadable_classes_allocated = 0; 
    loadable_classes_used = 0; 
    
    // Call all +loads for the detached list.
    for (i = 0; i < used; i++) { 
        Class cls = classes[i].cls;
        load_method_t load_method = (load_method_t)classes[i].method;
        if (!cls) continue;
        
        if (PrintLoading) { 
            _objc_inform("LOAD: +[%s load]\n", cls->nameForLogging()); 
        }
        (*load_method)(cls, @selector(load)); 
    }
    
    // Destroy the detached list. 
    if (classes) free(classes); 
}
  • call_class_loads:先循环调用主类的load方法

1.4call_category_loads

static bool call_category_loads(void) 
{
    int i, shift; 
    bool new_categories_added = NO; 
    
    // Detach current loadable list. 
    struct loadable_category *cats = loadable_categories; 
    int used = loadable_categories_used; 
    int allocated = loadable_categories_allocated; 
    loadable_categories = nil; 
    loadable_categories_allocated = 0; 
    loadable_categories_used = 0; 
    
    // Call all +loads for the detached list. 
    for (i = 0; i < used; i++) { 
        Category cat = cats[i].cat; 
        load_method_t load_method = (load_method_t)cats[i].method; 
        Class cls;
        if (!cat) continue;
        
        cls = _category_getClass(cat); 
        if (cls && cls->isLoadable()) { 
            if (PrintLoading) {
                _objc_inform("LOAD: +[%s(%s) load]\n", cls->nameForLogging(), _category_getName(cat)); 
            }
            (*load_method)(cls, @selector(load)); 
            cats[i].cat = nil; 
        }
    }
    
    // Compact detached list (order-preserving) 
    shift = 0; 
    for (i = 0; i < used; i++) { 
        if (cats[i].cat) { 
            cats[i-shift] = cats[i];
        } else { 
            shift++; 
        }
    }
    used -= shift; 
    
    // Copy any new +load candidates from the new list to the detached list. 
    new_categories_added = (loadable_categories_used > 0);
    for (i = 0; i < loadable_categories_used; i++) {
        if (used == allocated) { 
            allocated = allocated*2 + 16; 
            cats = (struct loadable_category *) realloc(cats, allocated * sizeof(struct loadable_category)); 
         }
         cats[used++] = loadable_categories[i]; 
     } 
     
     // Destroy the new list.
     if (loadable_categories) free(loadable_categories); 
     
     // Reattach the (now augmented) detached list. 
     // But if there's nothing left to load, destroy the list. 
     if (used) { 
         loadable_categories = cats;
         loadable_categories_used = used; 
         loadable_categories_allocated = allocated; 
     } else {
         if (cats) free(cats);
         loadable_categories = nil;
         loadable_categories_used = 0; 
         loadable_categories_allocated = 0;
     }
     
     if (PrintLoading) { 
         if (loadable_categories_used != 0) {
             _objc_inform("LOAD: %d categories still waiting for +load\n", loadable_categories_used); 
         }
     }
     
     return new_categories_added;
 }
  • call_category_loads:再循环调用分类的load方法