我是靠谱客的博主 糊涂月饼,最近开发中收集的这篇文章主要介绍load、initialize+(void)load、+(void)initialize,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

+(void)load、+(void)initialize

+load+initialize
调用时机编译时(runtime加载类和分类时 )类第一次接收到消息时
调用方式函数指针直接调用消息机制msg_send
  • +load方法

    • load方法会在runtime加载类、分类时调用
    • 每个类、分类+load,在程序运行过程中之调用一次
    • 调用顺序
      1. 调用类的+load
        • 按照编译先后顺序(先编译,先调用)
        • 调用子类的+load之前会先调用父类的+load
        • 如果父类在子类之前参与编译,先调用父类+load,子类不再调用
      2. 调用分类的+load
        • 按照编译先后顺序(先编译,先调用)
  • load方法源码追踪

    • objc-os -> _objc_init(runtime的入口)
    void _objc_init(void) {
    	// ...
    	_dyld_objc_notify_register(&map_images, load_images, unmap_image);
    	// load_images:
    }
    
    • objc-runtime-new/old -> load_images
    void load_images(const char *path __unused, const struct mach_header *mh) {
    	// ...
    	call_load_methods();
    }
    
    • objc-loadmethod -> call_load_methods
    void call_load_methods(void) {
       // ...
    	do {
            while (loadable_classes_used > 0) {
                call_class_loads();
            }
            // 2. Call category +loads ONCE
            more_categories = call_category_loads();
    	} while (loadable_classes_used > 0  ||  more_categories);
    	// ...
    }
    
    
    • objc-loadmethod -> call_class_loads
    static void call_class_loads(void)
    {
    	// ...
    	// 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));
    	}
    }
    
    • objc-loadmethod -> call_category_loads
    static bool call_category_loads(void) {
    	// 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;
    		}
    	}
    }
    
  • +initialize 方法

    • initialize方法在类第一次接收到消息时调用
    • 先调用父类的initialize、在调用自己的initialize。默认每一个类只调用一次
    • 如果分类实现了initialize,则会覆盖自身的initialize
    • 如果自类没有实现initialize,则会调用父类的initialize。所以父类的initialize有可能调用多次

最后

以上就是糊涂月饼为你收集整理的load、initialize+(void)load、+(void)initialize的全部内容,希望文章能够帮你解决load、initialize+(void)load、+(void)initialize所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部