NativeScript / plugins

@nativescript plugins to help with your developments.
https://docs.nativescript.org/plugins/index.html
Apache License 2.0
187 stars 104 forks source link

[imagepicker] IOS - Uncaught Error: The file *** couldn't be opened. #550

Open sommistica opened 7 months ago

sommistica commented 7 months ago

Issue: Every once in a while the following error occurs when selecting an image with the image picker. This mostly happens "the first time" a picure is selected after opening the app. Following the exact same steps most times the imagepicker works as expected without throwing the error. It only occurs sometimes without any changes to the code, process, etc. Sentry tells it happens more often. The issue happens on IOs 16.4, and 17.1, and probally other versions.

Log:

on device 9B1D4E42-9CE9-452E-B84F-EE40C6D438F4. Error while parsing debug response object. Error: BINDINGS: string value expected authorizing... Fatal JavaScript exception - application has been terminated. NativeScript encountered a fatal error: Uncaught Error: The file ‚ *** couldnt' be opened. at _loop_2(file: src/webpack:/groeigids/node_modules/@nativescript/imagepicker/index.ios.js:142:0) at (file: src/webpack:/groeigids/node_modules/@nativescript/imagepicker/index.ios.js:152:0) at timer(file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:2561:0) at invokeTask(file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:406:0) at runTask(file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:178:0) at invokeTask(file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:487:0) at ZoneTask.invoke(file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:476:0) at data.args.(file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:2541:0) at invoke(file: src/webpack:/groeigids/node_modules/@nativescript/core/timer/index.ios.js:54:0) at invoke(file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:372:0) at runGuarded(file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:144:0) at (file: src/webpack:/groeigids/node_modules/zone.js/fesm2015/zone.js:128:0) at TimerTargetImpl.tick(file: src/webpack:/groeigids/node_modules/@nativescript/core/timer/index.ios.js:18:0)

Code and setup: public pickImage(options?: OptionsCommon, hostView?: View): Promise { // Create image picker const p = imagePicker.create({ mode: 'single', maximumNumberOfSelection: 1, mediaType: ImagePickerMediaType.Image, }, hostView); // Hostview is important to render on top of a modal

// Authorization is required (allow app to ...)
return p.authorize()
  .then(() => p.present()) // Present the imagepicker
  .then((selection) => {
    const imagePickerSelection = selection[0];
    return Promise.all([Promise.resolve(imagePickerSelection.asset), isIOS ?
      ImageSource.fromAsset(imagePickerSelection.asset) : null]);
  })
  .then((f: [ImageAsset, ImageSource]) => this.processPickedImage(f, options))
  .catch(reason => Promise.reject(this.processPickingFailure(reason)));

}

The key NSPhotoLibraryUsageDescription has been added to info.plist

The error occurs after the p.present() and picking the image.

hendrickson-tyler commented 7 months ago

Yep, exact same issue here on the latest version (v3.0.1). In fact, every release since v2 has always resulted in this error on iOS. I believe it has to do with iCloud Photo Library when you select a photo that isn't downloaded on the device. Recent photos in my library work fine, but if I try to select an older photo that I haven't looked at in a while, the app crashes. Not sure if your experience is the same. No issues on the simulator because that doesn't use iCloud Photo Library.

You might need to downgrade to v1.0.10, which is the version I've been stuck on because of this issue. Would love to use the latest, but this is a show-stopper.

hendrickson-tyler commented 7 months ago

Apologies for the double post. Looking into this further, it seems like a workaround is to set the copyToAppFolder option when creating the ImagePicker instance like so:

const imagePicker = create({
  mode: 'single',
  mediaType: ImagePickerMediaType.Image,
  prompt: 'Select a photo',
  copyToAppFolder: 'selected-images', // Fixes the issue. Can be named anything.
});

I do still see an error in the console:

Error copying file:  Error: file is directory

Despite this, everything seems to work and I have not seen a crash—even when selecting images that were previously problematic.

Not sure why this is required now and I'm not sure of potential side effects. Do we need to manually clear this app folder to prevent it from bloating unnecessarily? Hoping somebody a little more familiar with the plugin can comment 🙂