[expo-gl] iOS app crash when using "capture" method

Hello, I’m building app that take pictures.
User can edit those pictures and he can update brightness and contrast.

To build the app with React Native (without Expo) I am using these dependencies:

"gl-react": "4.0.1",
"gl-react-native": "4.0.1",
"react-native-unimodules": "^0.14.6",

I have a component called “BrightnessAndContrast”:

import React, { useRef, useState } from 'react'
import { Shaders, Node, GLSL } from 'gl-react'
import { Surface } from 'gl-react-native'

const shaders = Shaders.create({
  Saturate: {
    frag: GLSL`
  precision highp float;
  varying vec2 uv;
  uniform sampler2D t;
  uniform float contrast, saturation, brightness;
  const vec3 L = vec3(0.2125, 0.7154, 0.0721);
  void main() {
    vec4 c = texture2D(t, uv);
      vec3 brt = c.rgb * brightness;
      gl_FragColor = vec4(mix(
      vec3(0.5),
      mix(vec3(dot(brt, L)), brt, saturation),
      contrast), c.a);
  }`
  }
})

const Saturate = ({
  contrast,
  saturation,
  brightness,
  children
}) => (
  <Node
    shader={shaders.Saturate}
    uniforms={{ contrast, saturation, brightness, t: children }}
  />
)

const BrightnessAndContrast = ({ onSave, uri }) => {
  const surfaceRef = useRef<Surface>(null)
  const [contrast, setContrast] = useState(1)
  const [brightness, setBrightness] = useState(1)

  const handleOnSaveImage = async () => {
    try {
      const result = await surfaceRef.current?.glView.capture() // <-- this line crash on iOS
      onSave(result.uri)
    } catch (error) {
      console.log(error)
    }
  }

  return (
    <Container>
      <Surface ref={surfaceRef} style={{ width: 320, height: 320 }}>
        <Saturate {...{ brightness, contrast, saturation: 1}}>
          {{ uri }}
        </Saturate>
      </Surface>
      <Footer>
          {/* other code... */}
          <ButtonIcon
            onPress={handleOnSaveImage}
            renderIcon={() => <Check color='#FFF' />}
            text='Save'
          />
      </Footer>
    </Container>
  )
}

export { BrightnessAndContrast }

It works fine on Android, but on iOS, when I press “Save” and invoke the capture method, the app crashes with the following error:

2021-09-03 10:28:21.458968+0200 AwesomeApp[629:101590] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter'
*** First throw call stack:
(0x1de90b180 0x1ddae39f8 0x1de8153a0 0x1df28a044 0x1df289fac 0x10077eefc 0x10077d8d4 0x10077da40 0x105f7b6f4 0x105f7cc78 0x105f84bf4 0x105f858b4 0x105f8f77c 0x1de52a114 0x1de52ccd4)
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter'
terminating with uncaught exception of type NSException
(lldb)

After debugging I saw this method generateSnapshotPathWithExtension in EXGL/EXGLContext.m that give me error on line 285. This line return nil:

NSString *directory = [fileSystem.cachesDirectory stringByAppendingPathComponent:@"GLView"];

It works if I replace this string with

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
  NSString *directory = [paths objectAtIndex:0];

Is this a known issue? Or am I missing something?

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.