关于cocoapods里pod编译的问题
前一段时间公司的APP要支持webp格式的图片
所以引入了SDWebImage的子模块WebP
WebP模块有一个UIImage的扩展
内容大概是这样(去掉了一些不相关的代码)
#ifdef SD_WEBP
#import <UIKit/UIKit.h>
@interface UIImage (WebP)
+ (UIImage *)sd_imageWithWebPData:(NSData *)data;
@end
#endif
也就是说这个头文件会检查是否有SD_WEBP这个宏定义
如果有才会声明这个类方法(当然.m文件中也有类似的处理)
业务线的代码都是作为Pod引入的
当时在eLongHome这个Pod中使用了这个类方法
然后问题来了
编译失败
报错是没有找到这个方法
我勒个去
SD_WEBP的声明不是已经自动添加了么
为毛还会有这个错误
之后我对这个问题研究了几天
得出了一下成果:
cocoapods对每个Pod都是单独编译然后把所有的Pod打包成一个libPods.a文件
在对使用了这个类方法的文件进行编译的时候
编译器发现这个类方法是需要SD_WEBP这个宏定义的
然后去当前文件所引用的宏定义里去找
主要有这么几个位置
1.当前文件中的声明,即在这个.m文件里的define语句
2.当前文件所引用的.h文件(包括引用的.h文件引用的头文件,依次往上查找,能找到就算),这个.h文件位置随意,可以在其他Pod中
3.Pod的工程文件中,该Pod所对应的target中的Building Settings中的宏定义设置(Preprocessor Macros)
只要在这几个位置有SD_WEBP的声明,就可以编译通过
不过我仔细想了一下
既然是单独编译的
那不是只要SDWebImage在编译的时候能找到SD_WEBP这个宏定义不就可以了么
为什么必须要使用的位置也要声明
在经过一番思考之后我只得出了一个合法的猜测
使用该类方法时所声明的宏定义仅用于编译检查,与实际使用无关(也就是说其实是可以执行的只是编译不给过) 验证的过程也非常简单
OC本身有runtime的特性
用performSelector绕过编译检查就可以了
实际结果证明了我的猜测是正确的
在探索的过程中还有一个细节是我以前没有注意到的
那就是预处理命令是有顺序的
这些写法是合法的
1.
#define SD_WEBP 1
#import "UIImage+WebP.h"
2.
#import "Test.h" // Test.h中有SD_WEBP的宏定义或者Test.h所引用的头文件中有,依次往上查找能找到就算
#import "UIImage+WebP.h"
这些写法是不合法的
1.
#import "UIImage+WebP.h"
#define SD_WEBP 1
2.
#import "UIImage+WebP.h"
#import "Test.h" // Test.h中有SD_WEBP的宏定义或者Test.h所引用的头文件中有,依次往上查找能找到就算
以上