TLDR:
项目中有一个SDK向外暴露了NS_OPTIONS宏,我修正了宏的值,导致逻辑问题。NS_OPTIONS本质是宏,A组件使用了B组件的NS_OPTIONS,当A组件构建为二进制包时,预编译期会将NS_OPTIONS变量替换为固定的值。一旦B组件修正了NS_OPTIONS的值,A组件就会出现逻辑Bug。
详细描绘:
事情是这样,我开发一个需求,涉及A和B两个模块,它们是独立的二进制组件。A模块有一个NS_OPTIONS,名称是XXPresentationOption,代码如下。
typedef NS_OPTIONS(NSInteger, XXPresentationOption) {
XXPresentationOptionDefault,
XXPresentationOptionBlocking,
XXPresentationOptionLight,
XXPresentationOptionEnableSwipe
};
我开发B模块时,使用了XXPresentationOptionEnableSwipe判别当前是否敞开下拉封闭功用,代码如下。
XXPresentationOption myOption = XXPresentationOptionEnableSwipe
测试时发现有bug,原因是没用bitmast声明NS_OPTIONS,导致options会过错地命中XXPresentationOptionBlocking。
if (self.options & XXPresentationOptionBlocking) {
return;
}
于是,我改为bitmst声明,代码如下。
typedef NS_OPTIONS(NSUInteger, XXPresentationOption) {
XXPresentationOptionDefault = 0,
XXPresentationOptionBlocking = 1 << 0,
XXPresentationOptionLight = 1 << 1,
XXPresentationOptionEnableSwipe = 1 << 2
};
修正后的逻辑本地测试正常,集成A模块测试却发现有逻辑Bug。本地代码和CI平台代码一样,逻辑却不同,这让我怀疑人生!!!通过一番调试,发现B模块中options的值不对。
代码写的是options = XXPresentationOptionEnableSwipe,但实际上options是XXPresentationOptionBlocking | XXPresentationOptionLight。
我对比了改动前后的差异,修正前XXPresentationOptionEnableSwipe是3,修正后XXPresentationOptionEnableSwipe是4。XXPresentationOptionBlocking | XXPresentationOptionLight是3,正好是修正前的XXPresentationOptionEnableSwipe。
我忽然晃过神来,我修正A模块后,并没有重新构建B模块。NS_OPTIONS是宏,所以B模块依靠的XXPresentationOptionEnableSwipe仍是修正前的3。
总结:
组件要尽量防止对外暴露NS_OPTIONS或NS_ENUM宏,假如必定得暴露,不能修正它们的值。