运行 ios 模拟器时出现错误。我一登录,应用程序就崩溃了。
我在分支主管上,一切正常。我创建了一个新分支“android”并运行了 android 模拟器,修复了一些与 android 相关的问题。然后我想确保在 iPhone 中看起来仍然不错,所以我跑到了 iPhone 模拟器,这就是我遇到错误的时候。屏幕不会立即崩溃。我一登录就崩溃。android模拟器虽然运行得很好。我想我会使用“git checkout master”分支来查明导致该错误的确切原因,但该错误仍然存在于 master 分支上。这对我来说没有多大意义。
这是我的堆栈跟踪:
Malformed calls from JS: field sizes are different.
[[74,24],[19,1],[[64,2000,1552169087432,false]],415]
RCTFatal
-[RCTCxxBridge handleError:]
__34-[RCTCxxBridge _initializeBridge:]_block_invoke
facebook::react::RCTMessageThread::tryFunc(std::__1::function<void ()> const&)
facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1::operator()() const
void std::__1::__invoke_void_return_wrapper::__call<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&&&)
std::__1::__function::__func<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1, std::__1::allocator<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1>, void ()>::operator()()
std::__1::function<void ()>::operator()() const
invocation function for block in facebook::react::RCTMessageThread::runAsync(std::__1::function<void ()>)
CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK
__CFRunLoopDoBlocks
__CFRunLoopRun
CFRunLoopRunSpecific
+[RCTCxxBridge runRunLoop]
NSThread__start
_pthread_body
_pthread_body
thread_start
Run Code Online (Sandbox Code Playgroud)
我不知道如何调试这个问题。它无处不在,恢复到以前的提交也无济于事。错误详细信息并没有给我太多的工作。请帮忙!
这是我的 package.json 依赖项:
"@babel/core": "^7.3.3",
"antd-mobile-rn": "^2.2.1",
"axios": "^0.18.0",
"babel-eslint": "^8.2.2",
"bugsnag-react-native": "^2.14.0",
"bugsnag-sourcemaps": "^1.1.0",
"moment": "^2.24.0",
"node": "^10.15.1",
"npm": "^6.7.0",
"prop-types": "^15.6.1",
"react": "^16.7.0",
"react-native": "^0.58.4",
"react-native-alert-async": "^1.0.3",
"react-native-aws3": "0.0.8",
"react-native-cached-image": "^1.4.3",
"react-native-country-picker-modal": "^0.7.1",
"react-native-elements": "^0.19.0",
"react-native-modalbox": "^1.7.1",
"react-native-photo-upload": "^1.3.0",
"react-native-push-notification": "^3.1.2",
"react-native-router-flux": "^4.0.0-beta.28",
"react-native-step-indicator": "0.0.9",
"react-native-swiper": "^1.5.14",
"react-native-vector-icons": "^4.6.0",
"react-navigation": "^2.18.3",
"rn-fetch-blob": "^0.10.15",
"socks": "^2.3.0",
"tinycolor2": "^1.4.1"
Run Code Online (Sandbox Code Playgroud)
让我知道我可以提供哪些额外信息。
Sud*_*Plz 15
这是一个非常普遍(且复杂)的错误,其背后可能有多种原因,因此我将发布 2 种解决此问题的方法,一种“可能”有效的简单方法,以及一种“肯定会”的更难方法“ 工作。
首先消除悬而未决的果实(NaN,Infinity 问题):
第 1 步:复制完整的错误消息,将其粘贴到文本编辑器中,甚至可以使用https://beautifier.io/ 之类的内容对其进行美化
第 2 步:搜索字符串NaN或字符串Infinit。
如果幸运的话,您会注意到您可能不小心将NaN值作为组件样式或组件 prop传递。修复该值将解决问题。您将如何确定是哪个组件或样式,您将检查 NaN 值周围的信息。(即您在相同的样式上传递一个 fontName: 'whatever' ,这会泄露问题所在)
为什么会抛出该错误 - 以及一些上下文:
(如果你不关心上下文,你可以直接跳到“如何排除故障”部分)
您可能知道,react-native 过去常常使用 react-native 桥将信息传递给本机端。为此,它使用了一种非常奇怪的数组格式,所以让我们看看上面的错误:
[
[74, 24],
[19, 1],
[
[64, 2000, 1552169087432, false]
], 415
]
Run Code Online (Sandbox Code Playgroud)
这是一个批处理桥消息,这基本上意味着,一系列消息通过桥发送(因为 react-native 将它们批处理以节省资源)。
第一个数组包含被调用的模块 ID
所述第二阵列包含模块方法ID所调用的
所述第三阵列包含PARAMS给予的那些方法。
在上面的例子中,模块 74调用了方法 19并被赋予了参数[64, 2000, 1552169087432, false]
在这里可以很容易地识别问题,因为调用方法 1的第二个调用模块 24期望参数,但没有任何参数作为参数传递给它。为了调用正确,第三个数组应该包含另一个子元素(如下所示:
[
[74, 24],
[19, 1],
[
[64, 2000, 1552169087432, false],
[] // <-- that was missing
], 415
]
Run Code Online (Sandbox Code Playgroud)
因此field sizes are different
错误。那是因为 react-native 期望对于每个给定的调用,所有3 个字段都应该包含 information。
缺少 params 的原因是因为我们的一个模块不喜欢我们的输入之一(特别是我们传递的参数类型)并决定静默崩溃。我们的应用程序没有崩溃,但通过桥发送了错误的信息。
话虽如此,我们现在必须做的就是找出问题所在:
为了找出故障制造者模块是谁,我们将检查在上述批处理消息中通过桥发送的所有消息方法调用(如我们的崩溃日志中所示)。
以上述问题为例。为了解决这个问题,我们需要找出 id 为 74 的模块是哪个模块(模块名称),以及 id 为 19 的方法的方法名称是什么(方法名称)。
然后,我们将对崩溃报告中看到的每个调用序列重复相同的过程。
即 id 为 24 的模块,id 为 1 的方法
这里的目标是找出导致崩溃的本地模块和方法调用,由于所有 RN 本地模块调用都通过桥,我们可以很容易地实现这一点。
我们现在需要的是一种将这些 id 转换为实际模块名称和方法名称的方法。我们很幸运,因为 react-native 通过BatchedBridge公开了这些信息。创建模块时(通常在应用程序启动时)react-native 会保留对模块 id 和方法 id 的引用。我们将利用它来获取我们需要的模块/方法名称。
第 1 步:在代码中的任意位置添加以下代码片段:
if (global.__fbBatchedBridge) {
const origMessageQueue = global.__fbBatchedBridge;
const modules = origMessageQueue._remoteModuleTable;
const methods = origMessageQueue._remoteMethodTable;
global.findModuleByModuleAndMethodIds = (moduleId, methodId) => {
console.log(`The problematic line code is in: ${modules[moduleId]}.${methods[moduleId][methodId]}`)
}
}
Run Code Online (Sandbox Code Playgroud)
第 2 步:您现在要做的就是在应用程序的任何位置设置断点,然后尝试将模块/方法 ID 对作为global.findModuleByModuleAndMethodIds
函数的参数,如下所示:
global.findModuleByModuleAndMethodIds(74, 19);
global.findModuleByModuleAndMethodIds(24, 1);
Run Code Online (Sandbox Code Playgroud)
这将打印嫌疑人的名字。从那时起,您将能够更好地找出问题所在。
例如,第一个调用可能会打印如下内容:(Timing.createTimer
这是 react-native 发送的典型消息setTimeout
,可能与您的崩溃无关。
第 3 步:调查这些调用中的每一个,并查找传递给这些本机函数的错误/奇怪的参数。
对我来说,其中一个调用输出:RNFBAnalyticsModule.logEvent
这让我调查了我们如何将事件记录到 firebase(就在崩溃时)却发现我们正在传递 amoment
作为它的道具之一。Firebase 不喜欢那样并无声地崩溃,导致上述错误。
我希望可以为某人节省数小时的头痛 - 我花了数小时来发现上述所有内容。
我认为当你经过本地桥NaN
或其他地方时就会发生这种情况。Infinity
在我的代码中,它将如下所示:
class MyComponent extends React.Component
constructor() {
// wrong retrun value from `foo()`, this.myProperty will be `Infinity`
this.myProperty = foo();
}
// Component methods here....
myFancyFunction() {
// This code will encounter `Malformed calls from JS: field sizes are different`
// `[xxxx, "<<Infinity>>", xxxxxxxxx, true]`
this.timer = setInterval(() => {
//Do something
}, this.myProperty); //<-- should never be `Infinity` here
}
}
Run Code Online (Sandbox Code Playgroud)
非常感谢这个链接: #23835
归档时间: |
|
查看次数: |
14447 次 |
最近记录: |