组件化项目使用NS_OPTIONS宏的坑

简介: TLDR:项目中有一个SDK向外暴露了NS_OPTIONS宏,我修改了宏的值,导致出现Bug。NS_OPTIONS本质是宏,A组件使用了B组件的NS_OPTIONS,当A组件构建为二进制包时,预编译期会将NS_OPTIONS变量替换为固定的值。一旦B组件修改了NS_OPTIONS的值,A组件就会出现逻辑Bug。具体描述:事情是这样,我开发一个需求,涉及A和B两个模块,它们是独立的二进制组件。A模块

TLDR:

项目中有一个SDK向外暴露了NS_OPTIONS宏,我修改了宏的值,导致出现Bug。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

我对比了改动前后的差异,修改前XXPresentationOptionEnableSwipe3,修改后XXPresentationOptionEnableSwipe4XXPresentationOptionBlocking | XXPresentationOptionLight3,正好是修改前的XXPresentationOptionEnableSwipe

我突然晃过神来,我修改A模块后,并没有重新构建B模块。NS_OPTIONS是宏,所以B模块依赖的XXPresentationOptionEnableSwipe还是修改前的3

总结:

组件要尽量避免对外暴露NS_OPTIONSNS_ENUM宏,如果一定得暴露,不能修改它们的值。

相关文章
|
2月前
|
JavaScript 前端开发
JS高级—call(),apply(),bind()
【10月更文挑战第17天】call()`、`apply()`和`bind()`是 JavaScript 中非常重要的工具,它们为我们提供了灵活控制函数执行和`this`指向的能力。通过合理运用这些方法,可以实现更复杂的编程逻辑和功能,提升代码的质量和可维护性。你在实际开发中可以根据具体需求,选择合适的方法来满足业务需求,并不断探索它们的更多应用场景。
11 1
|
5月前
|
API
Vue2和Vue3的区别,OptionsAPI与CompositionAPI的区别,Vue2所有的数据,都写在data和method方法中,setup是一个全新的配置项,Vue2是选项式API的写法
Vue2和Vue3的区别,OptionsAPI与CompositionAPI的区别,Vue2所有的数据,都写在data和method方法中,setup是一个全新的配置项,Vue2是选项式API的写法
|
7月前
|
缓存 JavaScript UED
vue中keep-alive的用法和含义
Vue.js 的 `&lt;keep-alive&gt;` 组件用于缓存不活动的组件实例,避免销毁并优化性能。当组件切换时,状态得以保持。用法是将其作为包裹组件,包含需缓存的组件。例如,在切换 `ComponentA` 和 `ComponentB` 时,利用 `&lt;keep-alive&gt;` 可以在状态间切换而不会丢失信息。此外,结合 `&lt;router-view&gt;` 可缓存路由组件,`include` 和 `exclude` 属性则能指定缓存特定组件,提升应用性能和用户体验。
45 1
09avalon - vm是如何作用视图
09avalon - vm是如何作用视图
55 0
|
7月前
|
JavaScript
call、apply、bind的使用场景区分(js的问题)
call、apply、bind的使用场景区分(js的问题)
26 0
|
JavaScript API
64Vue - Slots 分发内容(编译作用域)
64Vue - Slots 分发内容(编译作用域)
32 0
|
JavaScript 前端开发 API
Vue 实例及构造选项 options
Vue 实例及构造选项 options
160 0
|
JSON 前端开发 JavaScript
React(Hook)+TS+axios+ant design+json server实现todolist效果(整体目录结构设计)
React(Hook)+TS+axios+ant design+json server实现todolist效果(整体目录结构设计)
142 0
|
前端开发
前端hook项目pc总结笔记-Ts限制父子组件传值类型
前端hook项目pc总结笔记-Ts限制父子组件传值类型
79 0
|
JavaScript 前端开发
浅谈JS中call()和apply()的区别和用途?
前言: 在JavaScript中,this指向问题一直是一个老生常谈的问题。很多小伙伴应该都知道在js中,this指向哪里通常是在函数调用的时候才确定的,简单来说就是谁调用了函数则this指向谁,当然,这只是狭义的,更加详细的介绍大家可以去看《你不知道的Javascript》这本书。 call()和apply()这两个方法的作用可以简单归纳为改变this指向,从而让我们的this指向不在是谁调用了函数就指向谁。
160 1
浅谈JS中call()和apply()的区别和用途?