load、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有可能调用多次
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值