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

Image cannot show image in iOS 14 #29279

Closed
caofeng opened this issue Jul 6, 2020 · 205 comments · Fixed by department-of-veterans-affairs/va-mobile-app#443
Closed

Image cannot show image in iOS 14 #29279

caofeng opened this issue Jul 6, 2020 · 205 comments · Fixed by department-of-veterans-affairs/va-mobile-app#443
Labels
Component: Image Needs: Author Feedback Needs: Issue Template This issue does not make use of the Issue Template, and may be missing necessary information. Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.

Comments

@caofeng
Copy link

caofeng commented Jul 6, 2020

Image cannot show image in iOS 14, but can show location, like:
<Image
source={
require('./images/add_scan_images.png')
}
/>

Environment:
Xcode Version 12.0 beta (12A6159)
Simulator: IPhone SE - 2nd generation - 14.0
"react": "16.11.0",
"react-native": "0.62.2"

@react-native-bot react-native-bot added Component: Image Platform: iOS iOS applications. Needs: Author Feedback Needs: Environment Info Please run `react-native info` and edit your issue with that command's output. and removed Needs: Triage 🔍 labels Jul 6, 2020
@github-actions
Copy link

github-actions bot commented Jul 6, 2020

⚠️ Missing Environment Information
ℹ️ Your issue may be missing information about your development environment. You can obtain the missing information by running react-native info in a console.

@react-native-bot react-native-bot removed the Needs: Environment Info Please run `react-native info` and edit your issue with that command's output. label Jul 6, 2020
@tomas-sereikis
Copy link

Im facing the same issues

System:
    OS: macOS 10.16
    CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
    Memory: 493.38 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 14.4.0 - ~/.nvm/versions/node/v14.4.0/bin/node
    Yarn: 1.22.4 - ~/.nvm/versions/node/v14.4.0/bin/yarn
    npm: 6.14.5 - ~/.nvm/versions/node/v14.4.0/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.5, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 25, 27, 28, 29
      Build Tools: 28.0.3, 29.0.0
      System Images: android-27 | Google Play Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: 3.6 AI-192.7142.36.36.6308749
    Xcode: 11.5/11E608c - /usr/bin/xcodebuild
  Languages:
    Python: 2.7.16 - /usr/local/bin/python
  npmPackages:
    @react-native-community/cli: ^4.5.1 => 4.5.1 
    react: 16.11.0 => 16.11.0 
    react-native: 0.62.0 => 0.62.0 
  npmGlobalPackages:
    *react-native*: Not Found

however im on Xcode-beta and iOS 14

@tachtevrenidis
Copy link

i have the same issue!

@dmsouza
Copy link

dmsouza commented Jul 8, 2020

same issue...

1 similar comment
@jonathantroncoso82
Copy link

same issue...

@jennmueng
Copy link

jennmueng commented Jul 9, 2020

Ok so I've found that the issue with Images only happens when the build is made with Xcode 12 Beta. When I make a build using Xcode 11.5 using iOS 14.0 Beta Device Support gotten from here, Images work fine.

@QuintonC
Copy link

QuintonC commented Jul 9, 2020

This is a duplicate issue -- #29215

@hramos hramos added the Needs: Issue Template This issue does not make use of the Issue Template, and may be missing necessary information. label Jul 9, 2020
@github-actions
Copy link

github-actions bot commented Jul 9, 2020

⚠️ Missing Required Fields
ℹ️ It looks like your issue may be missing some necessary information. GitHub provides an example template whenever a new issue is created. Could you go back and make sure to fill out the template? You may edit this issue, or close it and open a new one.

@hramos hramos added the iOS 14 label Jul 9, 2020
@legion-zver
Copy link

Use react-native+0.63.0.patch

diff --git a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
index 21f1a06..2444713 100644
--- a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
+++ b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
@@ -272,6 +272,9 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
 
 - (void)displayLayer:(CALayer *)layer
 {
+  if (!_currentFrame) {
+    _currentFrame = self.image;
+  }
   if (_currentFrame) {
     layer.contentsScale = self.animatedImageScale;
     layer.contents = (__bridge id)_currentFrame.CGImage;
diff --git a/node_modules/react-native/scripts/.packager.env b/node_modules/react-native/scripts/.packager.env
new file mode 100644
index 0000000..361f5fb
--- /dev/null
+++ b/node_modules/react-native/scripts/.packager.env
@@ -0,0 +1 @@
+export RCT_METRO_PORT=8081

@Tucker2015
Copy link

Use react-native+0.63.0.patch

diff --git a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
index 21f1a06..2444713 100644
--- a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
+++ b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
@@ -272,6 +272,9 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
 
 - (void)displayLayer:(CALayer *)layer
 {
+  if (!_currentFrame) {
+    _currentFrame = self.image;
+  }
   if (_currentFrame) {
     layer.contentsScale = self.animatedImageScale;
     layer.contents = (__bridge id)_currentFrame.CGImage;
diff --git a/node_modules/react-native/scripts/.packager.env b/node_modules/react-native/scripts/.packager.env
new file mode 100644
index 0000000..361f5fb
--- /dev/null
+++ b/node_modules/react-native/scripts/.packager.env
@@ -0,0 +1 @@
+export RCT_METRO_PORT=8081

How can I apply this using patch-package please ? Beginner with using patch-package.

@artmerlop
Copy link

Use react-native+0.63.0.patch

diff --git a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
index 21f1a06..2444713 100644
--- a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
+++ b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
@@ -272,6 +272,9 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
 
 - (void)displayLayer:(CALayer *)layer
 {
+  if (!_currentFrame) {
+    _currentFrame = self.image;
+  }
   if (_currentFrame) {
     layer.contentsScale = self.animatedImageScale;
     layer.contents = (__bridge id)_currentFrame.CGImage;
diff --git a/node_modules/react-native/scripts/.packager.env b/node_modules/react-native/scripts/.packager.env
new file mode 100644
index 0000000..361f5fb
--- /dev/null
+++ b/node_modules/react-native/scripts/.packager.env
@@ -0,0 +1 @@
+export RCT_METRO_PORT=8081

How can I apply this using patch-package please ? Beginner with using patch-package.

Hi!

1.- run "npm i -g patch-package"
2.- Make a new folder called patches
3.- Make a new file called react-native+0.63.0.patch inside that folder
4.- Add the source code above.
5.- run "patch-package" on the root of the project

@Tucker2015
Copy link

Use react-native+0.63.0.patch

diff --git a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
index 21f1a06..2444713 100644
--- a/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
+++ b/node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m
@@ -272,6 +272,9 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
 
 - (void)displayLayer:(CALayer *)layer
 {
+  if (!_currentFrame) {
+    _currentFrame = self.image;
+  }
   if (_currentFrame) {
     layer.contentsScale = self.animatedImageScale;
     layer.contents = (__bridge id)_currentFrame.CGImage;
diff --git a/node_modules/react-native/scripts/.packager.env b/node_modules/react-native/scripts/.packager.env
new file mode 100644
index 0000000..361f5fb
--- /dev/null
+++ b/node_modules/react-native/scripts/.packager.env
@@ -0,0 +1 @@
+export RCT_METRO_PORT=8081

How can I apply this using patch-package please ? Beginner with using patch-package.

Hi!

1.- run "npm i -g patch-package"
2.- Make a new folder called patches
3.- Make a new file called react-native+0.63.0.patch inside that folder
4.- Add the source code above.
5.- run "patch-package" on the root of the project

Worked great thanks.

@tomcheung
Copy link

It can display the image after adding [super displayLayer:layer]; if _currentFrame is nil

if I understand correctly, _currentFrame should be for animated image, so if it is still image, we can use the UIImage implementation to handle image rendering, not sure if it is a correct fix.

- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
}
}

  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  } else {
    [super displayLayer:layer];
  }

grabbou pushed a commit that referenced this issue Jul 22, 2020
Summary:
This PR is to fix #29279, which image cannot show in iOS 14
As #29279 (comment) mention, this issue can be fixed by calling ` [super displayLayer:layer];` it it is still image, to let `UIImageView` handle still image rendering

## Changelog

[iOS] [Fixed] - Fix image cannot show in iOS 14

Pull Request resolved: #29420

Test Plan:
Image can be shown in iOS 14 build with Xcode 12 beta, using
```js
<Image source={require('./images/some_local_image.jpg')}/>
```

It may also need to test gif image is render correctly
```js
<Image source={{uri: 'https://some_remote_gif_image.gif'}}/>
```

Reviewed By: p-sun

Differential Revision: D22619448

Pulled By: shergin

fbshipit-source-id: f4d0ad83af945a6b8099d4eaea5a5f1933c7bfd2
tsapeta pushed a commit to expo/react-native that referenced this issue Jul 31, 2020
Summary:
This PR is to fix facebook#29279, which image cannot show in iOS 14
As facebook#29279 (comment) mention, this issue can be fixed by calling ` [super displayLayer:layer];` it it is still image, to let `UIImageView` handle still image rendering

## Changelog

[iOS] [Fixed] - Fix image cannot show in iOS 14

Pull Request resolved: facebook#29420

Test Plan:
Image can be shown in iOS 14 build with Xcode 12 beta, using
```js
<Image source={require('./images/some_local_image.jpg')}/>
```

It may also need to test gif image is render correctly
```js
<Image source={{uri: 'https://some_remote_gif_image.gif'}}/>
```

Reviewed By: p-sun

Differential Revision: D22619448

Pulled By: shergin

fbshipit-source-id: f4d0ad83af945a6b8099d4eaea5a5f1933c7bfd2
tsapeta pushed a commit to expo/react-native that referenced this issue Jul 31, 2020
Summary:
This PR is to fix facebook#29279, which image cannot show in iOS 14
As facebook#29279 (comment) mention, this issue can be fixed by calling ` [super displayLayer:layer];` it it is still image, to let `UIImageView` handle still image rendering

## Changelog

[iOS] [Fixed] - Fix image cannot show in iOS 14

Pull Request resolved: facebook#29420

Test Plan:
Image can be shown in iOS 14 build with Xcode 12 beta, using
```js
<Image source={require('./images/some_local_image.jpg')}/>
```

It may also need to test gif image is render correctly
```js
<Image source={{uri: 'https://some_remote_gif_image.gif'}}/>
```

Reviewed By: p-sun

Differential Revision: D22619448

Pulled By: shergin

fbshipit-source-id: f4d0ad83af945a6b8099d4eaea5a5f1933c7bfd2
tsapeta pushed a commit to expo/react-native that referenced this issue Jul 31, 2020
Summary:
This PR is to fix facebook#29279, which image cannot show in iOS 14
As facebook#29279 (comment) mention, this issue can be fixed by calling ` [super displayLayer:layer];` it it is still image, to let `UIImageView` handle still image rendering

## Changelog

[iOS] [Fixed] - Fix image cannot show in iOS 14

Pull Request resolved: facebook#29420

Test Plan:
Image can be shown in iOS 14 build with Xcode 12 beta, using
```js
<Image source={require('./images/some_local_image.jpg')}/>
```

It may also need to test gif image is render correctly
```js
<Image source={{uri: 'https://some_remote_gif_image.gif'}}/>
```

Reviewed By: p-sun

Differential Revision: D22619448

Pulled By: shergin

fbshipit-source-id: f4d0ad83af945a6b8099d4eaea5a5f1933c7bfd2
@LaurenceM10
Copy link

It can display the image after adding [super displayLayer:layer]; if _currentFrame is nil

if I understand correctly, _currentFrame should be for animated image, so if it is still image, we can use the UIImage implementation to handle image rendering, not sure if it is a correct fix.

- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
}
}

  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  } else {
    [super displayLayer:layer];
  }

This is not working for me.

@iamkkumar-dev
Copy link

It can display the image after adding [super displayLayer:layer]; if _currentFrame is nil
if I understand correctly, _currentFrame should be for animated image, so if it is still image, we can use the UIImage implementation to handle image rendering, not sure if it is a correct fix.

- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
}
}

  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  } else {
    [super displayLayer:layer];
  }

This is not working for me.

Have you resolved it?

@smanzini
Copy link

smanzini commented May 17, 2021

yes me too still having the same problem with RN 0.64,
all the images are visible in development mode but in release mode they all disappear.
any help ?

ok so i solved my problem in RN 0.64
i have created an asset folder inside of ios folder and i added this folder in Xcode (development asset) none of the images were visible in release mode.(works perfectly on development mode)
So i followed these steps and it solved my problem.
1- removed asset from Xcode (General -> Development Assets).
2-removed asset from Xcode(Build phases -> copy bundle sources)
3- moved the asset folder to the main root(outside of IOS folder).
4- used required to fetch local image.
"All the images works perfectly"
I'm new to mobile app development, What i discovered is that any time you use a local image with require while building the app all the used images will be automatically integrated into your app even if the folder is outside of Android or IOS folder.

hope this will help!
Screen Shot 2021-04-22 at 8 52 09 PM

hi @ralphbourji could you please clarify what do you mean with 4. used required to fetch local image ?
How can you link the Build Phases to the new asset folder then?
In my case I've created an 'Images.xcassets' folder under my project (under ios).
In the code I use <Avatar rounded source {{uri:'../ReactNative/NameProject/src/assets/images/Stefano.jpg'}} />
What happens to me is that images are correctly displayed on Simulator but not on Device.
Thanks

@smanzini
Copy link

It can display the image after adding [super displayLayer:layer]; if _currentFrame is nil
if I understand correctly, _currentFrame should be for animated image, so if it is still image, we can use the UIImage implementation to handle image rendering, not sure if it is a correct fix.

- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
}
}

  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  } else {
    [super displayLayer:layer];
  }

This is not working for me.

Have you resolved it?

Hello, what happens to me is that images are correctly displayed on Simulator but not on Device. Is that solving also issue on Device?
Thanks

@RidaRidss
Copy link

Thanks @tomcheung this quick fix worked for me , images were not showing on debug mode with the compilation of Xcode 12.5

It can display the image after adding [super displayLayer:layer]; if _currentFrame is nil

if I understand correctly, _currentFrame should be for animated image, so if it is still image, we can use the UIImage implementation to handle image rendering, not sure if it is a correct fix.

- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
}
}

  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  } else {
    [super displayLayer:layer];
  }

@WilbertJanney
Copy link

WilbertJanney commented Jun 3, 2021

Upgrading to React Native 0.63.4 fixed it for me since it has this fix included, but it works on the simulator and when building directly on the device. When I publish to an IPA file, it doesn't work. Anybody know why? I see other people are having the same issue. I'm using an Expo 41 ejected bare workflow React Native project. I had to move all of the images inside of the Images.xcassets to make it work, but it doesn't feel like the correct way to go about fixing it.

@brianedelman
Copy link

Been following this issue off an on for a while because none of these solutions have worked for me as the issue only happens in release mode on the device. https://stackoverflow.com/a/35366243/5282943 this solution fixed it for me finally. Hope this helps!

@fxricky
Copy link

fxricky commented Jul 26, 2021

I'm still facing this issue in react-native@0.64.2

@RidaRidss
Copy link

I'm still facing this issue in react-native@0.64.2

@fxricky you can try this , currently, i am using this snippet for this issue

#29279 (comment)

@smanzini
Copy link

smanzini commented Jul 26, 2021

@RidaRidss @fxricky But that's exactly what I've already on react-native/Libraries/Image/RCTUIImageViewAnimated.m (see below) and still not displaying images for device... :-(

RCTUIImageViewAnimated screenshot

@RidaRidss
Copy link

RidaRidss commented Jul 27, 2021

@RidaRidss @fxricky But that's exactly what I've already on react-native/Libraries/Image/RCTUIImageViewAnimated.m (see below) and still not displaying images for device... :-(

RCTUIImageViewAnimated screenshot

@smanzini here is the complete file, please replace it with the file exist in node modules, and then build app

/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#import <React/RCTUIImageViewAnimated.h>
#import <React/RCTWeakProxy.h>

#import <mach/mach.h>
#import <objc/runtime.h>

static NSUInteger RCTDeviceTotalMemory() {
  return (NSUInteger)[[NSProcessInfo processInfo] physicalMemory];
}

static NSUInteger RCTDeviceFreeMemory() {
  mach_port_t host_port = mach_host_self();
  mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
  vm_size_t page_size;
  vm_statistics_data_t vm_stat;
  kern_return_t kern;

  kern = host_page_size(host_port, &page_size);
  if (kern != KERN_SUCCESS) return 0;
  kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
  if (kern != KERN_SUCCESS) return 0;
  return (vm_stat.free_count - vm_stat.speculative_count) * page_size;
}

@interface RCTUIImageViewAnimated () <CALayerDelegate>

@property (nonatomic, assign) NSUInteger maxBufferSize;
@property (nonatomic, strong, readwrite) UIImage *currentFrame;
@property (nonatomic, assign, readwrite) NSUInteger currentFrameIndex;
@property (nonatomic, assign, readwrite) NSUInteger currentLoopCount;
@property (nonatomic, assign) NSUInteger totalFrameCount;
@property (nonatomic, assign) NSUInteger totalLoopCount;
@property (nonatomic, strong) UIImage<RCTAnimatedImage> *animatedImage;
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, UIImage *> *frameBuffer;
@property (nonatomic, assign) NSTimeInterval currentTime;
@property (nonatomic, assign) BOOL bufferMiss;
@property (nonatomic, assign) NSUInteger maxBufferCount;
@property (nonatomic, strong) NSOperationQueue *fetchQueue;
@property (nonatomic, strong) dispatch_semaphore_t lock;
@property (nonatomic, assign) CGFloat animatedImageScale;
@property (nonatomic, strong) CADisplayLink *displayLink;

@end

@implementation RCTUIImageViewAnimated

- (instancetype)initWithFrame:(CGRect)frame
{
  if (self = [super initWithFrame:frame]) {
    self.lock = dispatch_semaphore_create(1);
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];

  }
  return self;
}

- (void)resetAnimatedImage
{
  self.animatedImage = nil;
  self.totalFrameCount = 0;
  self.totalLoopCount = 0;
  self.currentFrame = nil;
  self.currentFrameIndex = 0;
  self.currentLoopCount = 0;
  self.currentTime = 0;
  self.bufferMiss = NO;
  self.maxBufferCount = 0;
  self.animatedImageScale = 1;
  [_fetchQueue cancelAllOperations];
  _fetchQueue = nil;
  dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
  [_frameBuffer removeAllObjects];
  _frameBuffer = nil;
  dispatch_semaphore_signal(self.lock);
}

- (void)setImage:(UIImage *)image
{
  if (self.image == image) {
    return;
  }

  [self stop];
  [self resetAnimatedImage];

  if ([image respondsToSelector:@selector(animatedImageFrameAtIndex:)]) {
    NSUInteger animatedImageFrameCount = ((UIImage<RCTAnimatedImage> *)image).animatedImageFrameCount;

    // In case frame count is 0, there is no reason to continue.
    if (animatedImageFrameCount == 0) {
      return;
    }

    self.animatedImage = (UIImage<RCTAnimatedImage> *)image;
    self.totalFrameCount = animatedImageFrameCount;

    // Get the current frame and loop count.
    self.totalLoopCount = self.animatedImage.animatedImageLoopCount;

    self.animatedImageScale = image.scale;

    self.currentFrame = image;

    dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
    self.frameBuffer[@(self.currentFrameIndex)] = self.currentFrame;
    dispatch_semaphore_signal(self.lock);

    // Calculate max buffer size
    [self calculateMaxBufferCount];

    if ([self paused]) {
      [self start];
    }

    [self.layer setNeedsDisplay];
  } else {
    super.image = image;
  }
}

#pragma mark - Private

- (NSOperationQueue *)fetchQueue
{
  if (!_fetchQueue) {
    _fetchQueue = [[NSOperationQueue alloc] init];
    _fetchQueue.maxConcurrentOperationCount = 1;
  }
  return _fetchQueue;
}

- (NSMutableDictionary<NSNumber *,UIImage *> *)frameBuffer
{
  if (!_frameBuffer) {
    _frameBuffer = [NSMutableDictionary dictionary];
  }
  return _frameBuffer;
}

- (CADisplayLink *)displayLink
{
  // We only need a displayLink in the case of animated images, so short-circuit this code and don't create one for most of the use cases.
  // Since this class is used for all RCTImageView's, this is especially important.
  if (!_animatedImage) {
    return nil;
  }

  if (!_displayLink) {
    _displayLink = [CADisplayLink displayLinkWithTarget:[RCTWeakProxy weakProxyWithTarget:self] selector:@selector(displayDidRefresh:)];
    NSString *runLoopMode = [NSProcessInfo processInfo].activeProcessorCount > 1 ? NSRunLoopCommonModes : NSDefaultRunLoopMode;
    [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:runLoopMode];
  }
  return _displayLink;
}

#pragma mark - Animation

- (void)start
{
  self.displayLink.paused = NO;
}

- (void)stop
{
  self.displayLink.paused = YES;
}

- (BOOL)paused
{
  return self.displayLink.isPaused;
}

- (void)displayDidRefresh:(CADisplayLink *)displayLink
{
#if TARGET_OS_UIKITFORMAC
  // TODO: `displayLink.frameInterval` is not available on UIKitForMac
  NSTimeInterval duration = displayLink.duration;
#else
  NSTimeInterval duration = displayLink.duration * displayLink.frameInterval;
#endif
  NSUInteger totalFrameCount = self.totalFrameCount;
  NSUInteger currentFrameIndex = self.currentFrameIndex;
  NSUInteger nextFrameIndex = (currentFrameIndex + 1) % totalFrameCount;

  // Check if we have the frame buffer firstly to improve performance
  if (!self.bufferMiss) {
    // Then check if timestamp is reached
    self.currentTime += duration;
    NSTimeInterval currentDuration = [self.animatedImage animatedImageDurationAtIndex:currentFrameIndex];
    if (self.currentTime < currentDuration) {
      // Current frame timestamp not reached, return
      return;
    }
    self.currentTime -= currentDuration;
    NSTimeInterval nextDuration = [self.animatedImage animatedImageDurationAtIndex:nextFrameIndex];
    if (self.currentTime > nextDuration) {
      // Do not skip frame
      self.currentTime = nextDuration;
    }
  }

  // Update the current frame
  UIImage *currentFrame;
  UIImage *fetchFrame;
  dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
  currentFrame = self.frameBuffer[@(currentFrameIndex)];
  fetchFrame = currentFrame ? self.frameBuffer[@(nextFrameIndex)] : nil;
  dispatch_semaphore_signal(self.lock);
  BOOL bufferFull = NO;
  if (currentFrame) {
    dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
    // Remove the frame buffer if need
    if (self.frameBuffer.count > self.maxBufferCount) {
      self.frameBuffer[@(currentFrameIndex)] = nil;
    }
    // Check whether we can stop fetch
    if (self.frameBuffer.count == totalFrameCount) {
      bufferFull = YES;
    }
    dispatch_semaphore_signal(self.lock);
    self.currentFrame = currentFrame;
    self.currentFrameIndex = nextFrameIndex;
    self.bufferMiss = NO;
    [self.layer setNeedsDisplay];
  } else {
    self.bufferMiss = YES;
  }

  // Update the loop count when last frame rendered
  if (nextFrameIndex == 0 && !self.bufferMiss) {
    // Update the loop count
    self.currentLoopCount++;
    // if reached the max loop count, stop animating, 0 means loop indefinitely
    NSUInteger maxLoopCount = self.totalLoopCount;
    if (maxLoopCount != 0 && (self.currentLoopCount >= maxLoopCount)) {
      [self stop];
      return;
    }
  }

  // Check if we should prefetch next frame or current frame
  NSUInteger fetchFrameIndex;
  if (self.bufferMiss) {
    // When buffer miss, means the decode speed is slower than render speed, we fetch current miss frame
    fetchFrameIndex = currentFrameIndex;
  } else {
    // Or, most cases, the decode speed is faster than render speed, we fetch next frame
    fetchFrameIndex = nextFrameIndex;
  }

  if (!fetchFrame && !bufferFull && self.fetchQueue.operationCount == 0) {
    // Prefetch next frame in background queue
    UIImage<RCTAnimatedImage> *animatedImage = self.animatedImage;
    NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
      UIImage *frame = [animatedImage animatedImageFrameAtIndex:fetchFrameIndex];
      dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
      self.frameBuffer[@(fetchFrameIndex)] = frame;
      dispatch_semaphore_signal(self.lock);
    }];
    [self.fetchQueue addOperation:operation];
  }
}

#pragma mark - CALayerDelegate

- (void)displayLayer:(CALayer *)layer
{
  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  } else {
    [super displayLayer:layer];
  }
}

#pragma mark - Util

- (void)calculateMaxBufferCount
{
  NSUInteger bytes = CGImageGetBytesPerRow(self.currentFrame.CGImage) * CGImageGetHeight(self.currentFrame.CGImage);
  if (bytes == 0) bytes = 1024;

  NSUInteger max = 0;
  if (self.maxBufferSize > 0) {
    max = self.maxBufferSize;
  } else {
    // Calculate based on current memory, these factors are by experience
    NSUInteger total = RCTDeviceTotalMemory();
    NSUInteger free = RCTDeviceFreeMemory();
    max = MIN(total * 0.2, free * 0.6);
  }

  NSUInteger maxBufferCount = (double)max / (double)bytes;
  if (!maxBufferCount) {
    // At least 1 frame
    maxBufferCount = 1;
  }

  self.maxBufferCount = maxBufferCount;
}

#pragma mark - Lifecycle

- (void)dealloc
{
  // Removes the display link from all run loop modes.
  [_displayLink invalidate];
  _displayLink = nil;
}

- (void)didReceiveMemoryWarning:(NSNotification *)notification
{
  [_fetchQueue cancelAllOperations];
  [_fetchQueue addOperationWithBlock:^{
    NSNumber *currentFrameIndex = @(self.currentFrameIndex);
    dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
    NSArray *keys = self.frameBuffer.allKeys;
    // only keep the next frame for later rendering
    for (NSNumber * key in keys) {
      if (![key isEqualToNumber:currentFrameIndex]) {
        [self.frameBuffer removeObjectForKey:key];
      }
    }
    dispatch_semaphore_signal(self.lock);
  }];
}

@end

@smanzini
Copy link

@RidaRidss I trust you, but just to know where did you find it? thx

@smanzini
Copy link

smanzini commented Jul 29, 2021

Finally I Made IT! :-) But without copying file from @RidaRidss :-)

@udaysagartammina
Copy link

@smanzini how do you fix that issue could you please explain me.

@smanzini
Copy link

Hello @udaysagartammina ,

  1. make sure to have super displayLayer:layer (as per image attached) in react-native/Libraries/Image/RCTUIImageViewAnimated.m
  2. make sure to have uploaded all the images within folder Images.xcassets (under MyProject folder, as per image attached)
  3. make sure to use in your code source={require('../../assets/images/xxx.jpg')}

Screenshot

Schermata 2021-07-29 alle 14 05 25

@udaysagartammina
Copy link

Hello @udaysagartammina ,

  1. make sure to have super displayLayer:layer (as per image attached) in react-native/Libraries/Image/RCTUIImageViewAnimated.m
  2. make sure to have uploaded all the images within folder Images.xcassets (under MyProject folder, as per image attached)
  3. make sure to use in your code source={require('../../assets/images/xxx.jpg')}

Screenshot

Schermata 2021-07-29 alle 14 05 25

@smanzini Thank you so much.

@snevula123456
Copy link

snevula123456 commented Aug 6, 2021

Still I am Facing the Issue images not displaying after building the IPA files
Details are available here #31968

@Anytram
Copy link

Anytram commented Aug 18, 2021

I also have this problem, newly added assets doesn't appear on iOS release version...

@syedamirali14
Copy link

syedamirali14 commented Aug 20, 2021

It can display the image after adding [super displayLayer:layer]; if _currentFrame is nil

if I understand correctly, _currentFrame should be for animated image, so if it is still image, we can use the UIImage implementation to handle image rendering, not sure if it is a correct fix.

- (void)displayLayer:(CALayer *)layer
{
if (_currentFrame) {
layer.contentsScale = self.animatedImageScale;
layer.contents = (__bridge id)_currentFrame.CGImage;
}
}

  if (_currentFrame) {
    layer.contentsScale = self.animatedImageScale;
    layer.contents = (__bridge id)_currentFrame.CGImage;
  } else {
    [super displayLayer:layer];
  }

this solution is not working for me
react native 0.63.3
chip apple m1

@KawaljeetCuelogic
Copy link

@syedamirali14 did you find any potential solution for this?

@cristianoccazinsp
Copy link
Contributor

cristianoccazinsp commented Sep 8, 2021

With RN 0.65, defaultSource and loadingIndicatorSource are not working on iOS, neither debug or release, when used with local images.

Actually, they don't show while the image is downloading, but if there's no connectivity, they show just fine.

@talaikis
Copy link

None of solutions work for 0.65.1 M1.

@cristianoccazinsp
Copy link
Contributor

This change here worked for me: #32172

@suraj-desai
Copy link

If anyone has ejected the app from expo :
https://forums.expo.dev/t/assets-missing-only-in-ios-release-build-after-ejecting/42759
This might help.
Happy coding!

@facebook facebook locked as resolved and limited conversation to collaborators Oct 1, 2021
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Oct 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Component: Image Needs: Author Feedback Needs: Issue Template This issue does not make use of the Issue Template, and may be missing necessary information. Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.
Projects
None yet