Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS "Camera Roll" Images rendering as white views #543

Open
aIacoella opened this issue Aug 16, 2019 · 20 comments
Open

iOS "Camera Roll" Images rendering as white views #543

aIacoella opened this issue Aug 16, 2019 · 20 comments
Labels

Comments

@aIacoella
Copy link

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 aIacoella added the bug label Aug 16, 2019
@Jarred-Sumner
Copy link

Jarred-Sumner commented Sep 5, 2019

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

@aIacoella
Copy link
Author

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

@eyu0415
Copy link

eyu0415 commented Nov 11, 2019

SDWebImagePhotosDefine.h in SDWebImagePhotosPlugin

the @import SDWebImage has error

"Module SDWebImage not found"

@bobber205
Copy link

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

@bobber205
Copy link

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

@bakerac4
Copy link

bakerac4 commented Dec 8, 2019

@dreampiggy Im also seeing the error above? Any ideas

@dreampiggy
Copy link
Contributor

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 ?

@priteshbaviskar
Copy link

@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.

@dreampiggy
Copy link
Contributor

dreampiggy commented Dec 12, 2019

@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
Copy link
Contributor

dreampiggy commented Dec 12, 2019

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
Copy link
Contributor

@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.

@pxpeterxu
Copy link

pxpeterxu commented Apr 28, 2020

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

@remigallego
Copy link

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.

@pxpeterxu
Copy link

@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.

@dreampiggy
Copy link
Contributor

dreampiggy commented Jul 7, 2020

@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
Copy link
Contributor

dreampiggy commented Jul 7, 2020

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
Copy link
Contributor

dreampiggy commented Jul 10, 2020

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 component size for querying image size).


PS: Is this repo still get maintained ? 😕

@exception
Copy link

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

@hantrungkien
Copy link

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

@dreampiggy
Copy link
Contributor

dreampiggy commented May 23, 2023

@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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests