众所周知,在iOS的Cocoa框架中的基类是NSObject,任何类都继承自这个基类。而最常使用的方法,无非就是alloc,init,copy这些,但是load这个方法却常被忽视。
+ (void)load;
点进去NSObject就可以看到:+(void)load方法是第一个方法,还在init之前。那么load方法有何德何能可以作为第一个方法?
以下是load方法的官方文档的简述:
Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
简单翻译就是:当一个类或者类别被加入到Objective-C runtime时才会被执行,在加载时可以在此方法中执行一些特殊行为。
那么这里有两个问题:
- 什么时候加入到Objective-C runtime,顺序是什么
- 实现此方法指定什么特殊行为
接下来一一解释:1.什么时候加入到Objective-C runtime,顺序是什么?
OC是在C基础之上发展起来的,而C是面向过程,OC是面向对象,从C到OC的过渡,期间就是基于runtime来实现的。可以简单理解为:runtime将其加载成一个类(语言太拙劣了,不太会表述)。
而一个工程会有很多类,其加入Runtime必然应该是有一个顺序的,这个顺序就是Objective-C文件build的顺序,其中build的顺序就是Target -> Build Phases -> Compile Sources的顺序。
以下是我写的YIIFMDB这个库的Build Phases:
在这个库当中有四个类:从上到下的顺序是ViewController,YIIParameters,AppDelegate和YIIFMDB,build的顺序也是按照这个顺序,同样的,+(void)load的顺序也是这个。大家可以验证一下。
有人谁说main.m呢?main.m严格意义来说并不是一个类,其只是决定了app的入口:从main函数开始。那么这个顺序就是:Runtime先将每一个类文件按照Compile Sources里的顺序进行build,然后进入main.m,程序开始运行。这就是所谓加入到Objective-C runtime的顺序。
这下就可以理解为为什么load方法回事NSObject的第一个方法了,排在initialize和init这两个初始化方法之前。
2.实现此方法指定什么特殊行为
官方文档当中有这样一句话:
In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.
这句话翻译起来很绕口,但是大意是:在load的自定义实现当中,你可以对其他不相关的类发送message,但是这些类的方法可能还没有调用。
最后会介绍其如何应用,先说load的一些其余知识点。
- 一个类的load方法是在所有父类的load方法调用完毕之后才被调用。(与init方法完全想反)
- Category的load方法又是在他所属的类的load方法调用完毕之后才调用
值得一提的是:Swift转成OC之后,loaded并不会自动加载,因为Swift没有Runtime这一机制,这一点在官方文档上也说了。
最后再说如何使用:
ShareSDK,Bugly等第三方库一般都会用到,而这些第三方的初始化配置好多人都是写在AppDelegate里的,但是这个样子会造成很多问题:
- 随着第三方库的增多,AppDelegate会写入越来越多的import
- 初始化配置代码越来越多,产生耦合,也导致AppDelegate越来越臃肿
- AppDelegate是UIApplication的代理,并不是让我们做第三方库初始化的
说了这么多总结起来就一点:第三方在AppDelegate初始化不好。这里就用到了load了。鉴于此方法是NSObject类和Category最开始加载的方法,对其进行一些初始化设置再合适不过了。
下面是使用的步骤(以ShareSDK为例):
1.创建一个类,姑且叫LCShare
2.在LCShare.m当中重写+ (void)load
3.在+ (void)load方法当中配置ShareSDK信息
(注:这个时候最大的缺点是编译环境并不安全,因为我们send message所到的类或许并未执行load方法)
同样的,我们在初始化配置Bugly,推送,统计,埋点等第三方库时,分别创建一个文件,在+ (void)load方法里进行配置就好了。
最后说一下组件化开发:组件化开发的思想之一就是去除无用的import,以达到模块间的解耦,如果分享,推送,统计,Bugly等模块都写好之后,好多工程都可以使用,而这些东西的初始化配置使用以上方法,小编觉得是最优雅的解决方案。
最后打个广告,个人第三方库:
UDUserDefaultsModel:NSUserDefaults的改进方案
YIIFMDB:直接操作Model进行增删改查,数学运算等,且sql语句易于管理