pmndrs / drei

šŸ„‰ useful helpers for react-three-fiber
https://docs.pmnd.rs/drei
MIT License
8.22k stars 671 forks source link

iOS production build crash: Calling the 'readAsStringAsync' function has failed in the latest react-native version #2054

Open lichmac opened 1 month ago

lichmac commented 1 month ago

Problem description:

I use the @react-three/drei lib to load the model from the folder /src/assets/models/male_anim.glb'. Android build works fine (production + debug build). iOS debug build works fine. iOS production build crashes when loading the above model

Could not load 38: Calling the 'readAsStringAsync' function has failed ā†’ Caused by: File '/var/containers/Bundle/Application/1D9F6806-70EA-46DE-91B9-3423D7E6577E/example.app/assets/src/assets/models/male_anim.glb' is not readable

Screenshot 2024-07-26 at 18 25 18 Screenshot 2024-07-26 at 18 36 26

FYI, the lib works fine in the old lib version (production + debug build). Below is the version of the old lib

"@react-three/drei": "^9.105.6",
"@react-three/fiber": "^8.16.6",
"expo": "^51.0.0",
"expo-gl": "~14.0.2",
"react": "18.2.0",
"react-native": "0.74.1",
"three": "^0.164.1",

Relevant code:

import { useAnimations, useFBX, useGLTF } from "@react-three/drei/native";
import { useFrame } from "@react-three/fiber/native";
import maleAnimPath from "../../assets/models/male_anim.glb";

  const animated = useMemo(() => useGLTF(
    maleAnimPath
  ), [gender]);

This is metro-config file

`const { getDefaultConfig } = require('expo/metro-config'); const { mergeConfig } = require('@react-native/metro-config');

/**

module.exports = mergeConfig(defaultConfig, config);`

Suggested solution:

paulmckee commented 1 month ago

I am running into the exact same problem: development build works fine, production build on iOS errors out because an asset isn't readable. I'm not using drei, though, so I think the actual issue is in Expo and/or React Native.

import { Asset } from 'expo-asset';
import * as FileSystem from 'expo-file-system';

  const asset = Asset.fromModule(require('@/assets/myFile.zip'));
  await asset.downloadAsync();
  // The following line throws an exception with code ERR_FILE_NOT_READABLE
  const zipFileBase64 = await FileSystem.readAsStringAsync(asset.localUri, { encoding: 'base64' });

Note that the error is ERR_FILE_NOT_READABLE, not ERR_FILE_NOT_EXISTS. The asset file is there inside the .ipa file.

The value of asset.localUri is something like file:///var/containers/Bundle/Application/xxxxxxxx-xxx-xxx-xxx-xxxxxxxxxxxx/myapp.app/assets/assets/myFile.zip.

I'm using the default metro configuration (in which, I believe, .zip files are supported as assets) and the following:

    "expo": "~51.0.22",
    "expo-asset": "~10.0.10",
    "expo-file-system": "~17.0.1",
    "react": "18.2.0",
    "react-native": "0.74.3",

Any thoughts or workarounds?