react-native-fast-image icon indicating copy to clipboard operation
react-native-fast-image copied to clipboard

iOS "Camera Roll" Images rendering as white views

Open aIacoella opened this issue 5 years ago • 20 comments

ONLY on iOS when rendering device cached images from camera roll the component renders white views.

Steps to reproduce the behavior:

  1. Get images paths from react native's camera roll
  2. Render FastImage with that uri

Expected behavior Normal image rendering.

Dependency versions

  • React Native version: 0.60.4
  • React version: 18.8.6
  • React Native Fast Image version: 7.0.2

aIacoella avatar Aug 16 '19 21:08 aIacoella

To add support for camera roll:

  1. Install this library: https://github.com/SDWebImage/SDWebImagePhotosPlugin
  2. Rewrite the source URI's you get from react-native-camera-roll to start with photos://asset/ instead of ph://

Example code (for step 2):

import FastImage from "react-native-fast-image";
import React from "react";
import hoistNonReactStatics from "hoist-non-react-statics";

const CustomFastImage = React.forwardRef(({ source, ...props }, ref) => {
  if (
    typeof source === "object" &&
    typeof source.uri === "string" &&
    source.uri.startsWith("ph://")
  ) {
    const { uri, ...otherSource } = source;
    return (
      <FastImage
        ref={ref}
        source={{
          uri: uri.replace("ph://", "photos://asset/"),
          ...otherSource
        }}
        {...props}
      />
    );
  } else {
    return <FastImage ref={ref} source={source} {...props} />;
  }
});

export const Image = hoistNonReactStatics(CustomFastImage, FastImage);

You'd also want to set it not to cache the images, or set the max cache size so that it doesn't fill up all your device's memory and then crash:

  [SDImageCache.sharedImageCache.config setMaxMemoryCost:50 * 1024 * 1024]; // 50 MB of memory
  [SDImageCache.sharedImageCache.config setMaxDiskSize:100 * 1024 * 1024]; // 100 MB of disk

Jarred-Sumner avatar Sep 05 '19 05:09 Jarred-Sumner

Thank you, I will definitely try this in the next days and I'll let you know.

aIacoella avatar Sep 06 '19 16:09 aIacoella

SDWebImagePhotosDefine.h in SDWebImagePhotosPlugin

the @import SDWebImage has error

"Module SDWebImage not found"

eyu0415 avatar Nov 11 '19 16:11 eyu0415

@eyu0415 Seeing the same thing after following the installation instructions.

bobber205 avatar Nov 12 '19 18:11 bobber205

@Jarred-Sumner Do you have an example project on with FastImage and RN and SDWebImage installed and working?

bobber205 avatar Nov 12 '19 19:11 bobber205

@dreampiggy Im also seeing the error above? Any ideas

bakerac4 avatar Dec 08 '19 15:12 bakerac4

SDWebImagePhotosDefine.h in SDWebImagePhotosPlugin

the @import SDWebImage has error

"Module SDWebImage not found"

What's the install method, why does not SDWebImage a clang module ? This import issue seems a little strange. Any demo here ?

dreampiggy avatar Dec 09 '19 03:12 dreampiggy

@dreampiggy I installed the plugin using CocoaPods as mentioned on https://github.com/SDWebImage/SDWebImagePhotosPlugin pod SDWebImagePhotosPlugin followed by pod install Running into the same issue.

priteshbaviskar avatar Dec 12 '19 10:12 priteshbaviskar

@dreampiggy I installed the plugin using CocoaPods as mentioned on https://github.com/SDWebImage/SDWebImagePhotosPlugin pod SDWebImagePhotosPlugin followed by pod install Running into the same issue.

Hi. @priteshbaviskar Can you provide a simple demo, contains:

  1. React-Native App
  2. Add react-native-fast-image
  3. Add react-native-camera-roll
  4. Add SDWebImagePhotosPlugin

So that I can find out the reason ?

From the description, I guess this maybe something project configuration related to react-native-fast-image (which bundle SDWebImage into the sub-project), does not supports clang module. Using standalone SDWebImage should support clang module and so works for that @import SDWebImage.

The @import SDWebImage is required to be used for Swift Pacage Manager support (Because it's a native library, React-Native users are one of our users), so we can not simply remove that. Need to find out a workaround.

dreampiggy avatar Dec 12 '19 10:12 dreampiggy

I guess I know the reason. CocoaPods's static library is not supported with module. I'll push a new version to support both of them (Sounds tricky)

For now, you can add this into your Podfile:

use_modular_headers! #important
pod 'SDWebImage', "~> 5.0"
pod 'SDWebImagePhotosPlugin', "~> 1.0"

dreampiggy avatar Dec 12 '19 11:12 dreampiggy

@priteshbaviskar @bakerac4 @bobber205 For the compile error of that module import, you can either upgrade to the Photos Plugin V1.0.1 version, or using the use_modular_headers! in CocoaPods instead. Which should fix it.

dreampiggy avatar Dec 13 '19 09:12 dreampiggy

EDIT (2020-07-06): I don't recommend using the SDImagePhotosPlugin on iOS. Especially if you're displaying more than one of these photos, you're going to be loading the full, 4000x3000 photos into memory (unlike react-native's <Image />, which loads approximately the correct size) which will cause out-of-memory errors. Instead, I recommend just using React Native <Image /> tags for on-device photos


Old comments below:

Thanks @dreampiggy for the pointers!

For those running into the same issue, these are the steps I took as of April, 2020 to get the photos displaying:

  1. Install SDWebImagePhotosPlugin by adding the following to your Podfile and then running pod install

    pod 'SDWebImagePhotosPlugin'
    
  2. Edit my AppDelegate.m:

    // At the top
    #import <SDWebImage/SDWebImage.h>
    #import <SDWebImagePhotosPlugin/SDImagePhotosLoader.h>
    
    // Within `didFinishLaunchingWithOptions`
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      // ...
      [SDImageLoadersManager.sharedManager addLoader:SDImagePhotosLoader.sharedLoader];
      SDWebImageManager.defaultImageLoader = SDImageLoadersManager.sharedManager;
    
      // ...
      // If there's no return statement already, add the following:
      return YES;
    }
    
  3. Build onto your device/simulator

Thanks @Jarred-Sumner for pointing me in the right direction! Note that that comment is a bit outdated now: ph://... URLs will already work out of the box, as @dreampiggy had added support in SDWebImagePhotosPlugin v1.0.0

pxpeterxu avatar Apr 28 '20 20:04 pxpeterxu

I followed your steps @pxpeterxu but it didn't solve the problem for me, I still have a white image in place of the actual image.

remigallego avatar Jul 07 '20 02:07 remigallego

@remigallego I actually don't recommend using the SDWebImagePhotosPlugin in general anymore after testing this with our app: SDWebImage doesn't have an idea of how large the photo to render should be, so it ends up loading the full-size, ~4000x3000 photo into memory. Instead, I recommend for now that you just use the regular react-native <Image /> to load these photos for now.

pxpeterxu avatar Jul 07 '20 03:07 pxpeterxu

@remigallego I actually don't recommend using the SDWebImagePhotosPlugin in general anymore after testing this with our app: SDWebImage doesn't have an idea of how large the photo to render should be, so it ends up loading the full-size, ~4000x3000 photo into memory. Instead, I recommend for now that you just use the regular react-native <Image /> to load these photos for now.

See Readme. We already provide the Native API to control the Photo loading size, rendering mode, image type (Normal Image/LivePhoto/GIF/Video Poster).

// request-level options
// allows iCloud Photos Library
let requestOptions = PHImageRequestOptions()
requestOptions.networkAccessAllowed = true
requestOptions.sd_targetSize = CGSize(width: 1000, 1000)
imageView.sd_setImage(with: photosURL, placeholderImage: nil, context:[.photosImageRequestOptions: requestOptions])

And I post this in the Warning chapter about the behavior.

image

The thing you can do, it's to write JavaScript wrapper. For example, you can pass through the style={{ width: 200, height: 200 }} to Native API. This is not the part of SDWebImage organization's duty because we don't have any JavaScript & React Native binding.

That it's react-native-fast-image or react-native-fast-image-photos's duty.


Maybe what I can do better, it's to write a standalone chapter about React Native user ? Changing the default behavior to return a smaller size of Photos Image, may not sounds reasonable.

Think if you're a framework author, what of size you should use to return to the user, if user don't provide any context information ?

dreampiggy avatar Jul 07 '20 07:07 dreampiggy

If you want to control a hard limit of size in global, you can do the same thing in Native API via

SDWebImageManager.shared.optionsProcessor = SDWebImageOptionsProcessor { options, context in
    var options = options ?: []
    var context = context ?: [:]
    // check if user have custom request options
    if let requestOptions = context[.photosImageRequestOptions] as? PHImageRequestOptions {
        // limit 1000x1000
        requestOptions.sd_targetSize = CGSize(width: 1000, 1000)
    } else {
        // if no customization, provide a default one with limit 1000x1000
        let requestOptions = PHImageRequestOptions()
        requestOptions.networkAccessAllowed = true
        requestOptions.sd_targetSize = CGSize(width: 1000, 1000)
        context[.photosImageRequestOptions] = requestOptions
    }
    return SDWebImageOptionsResult(options: options, context: context)
}

dreampiggy avatar Jul 07 '20 07:07 dreampiggy

SDWebImagePhotosPlugin released v1.1.0.

This version change the Default Query Image Size from full pixel size, into the largest size system provide (which is smaller than full size, based on iOS System optimization).

It's still recommended to use Native API to limit the fetch image size, until react-native-fast-image itself provide the JavaScript bridge API (for example, pass the <Image> component size for querying image size).


PS: Is this repo still get maintained ? 😕

dreampiggy avatar Jul 10 '20 10:07 dreampiggy

Almost a year later, this issue is still happening. Anyone got any idea on how to fix it properly?

exception avatar Feb 16 '21 22:02 exception

@dreampiggy PH Asset photo is loaded with SDWebImage Photos Plugin but PH asset video is white, do you have any solution?

hantrungkien avatar May 22 '23 15:05 hantrungkien

@hantrungkien I didn't test that PH asset video is white. Maybe a sample and re-producable demo is better for me to investigate.

And, you can fire a issue here https://github.com/SDWebImage/SDWebImagePhotosPlugin/issues/new/choose

dreampiggy avatar May 23 '23 06:05 dreampiggy