在iOS应用程序中输入背景时将图像的新副本加载到内存中

在iOS应用程序中输入背景时将图像的新副本加载到内存中,ios,react-native,Ios,React Native,我已经创建了一个全新的React原生项目(v0.60.4),并在真正的iPhone11Pro iOS 13.1.3上以发布模式运行它。app.js非常简单: 从“React”导入React; 进口{ 安全区域视图, 形象,, }从“反应本机”; 常量应用程序:()=>React$Node=()=>{ 返回( ); }; 导出默认应用程序; 我注意到,每次我的应用程序进入后台(当我切换到另一个应用程序时),我都会看到一个从未释放的内存使用跳跃(即使有内存警告) 我可以看出,增加是由一个新的Im

我已经创建了一个全新的React原生项目(v0.60.4),并在真正的iPhone11Pro iOS 13.1.3上以发布模式运行它。app.js非常简单:

从“React”导入React;
进口{
安全区域视图,
形象,,
}从“反应本机”;
常量应用程序:()=>React$Node=()=>{
返回(
);
};
导出默认应用程序;
我注意到,每次我的应用程序进入后台(当我切换到另一个应用程序时),我都会看到一个从未释放的内存使用跳跃(即使有内存警告)

我可以看出,增加是由一个新的ImageIO_PNG_数据引起的,该数据是在应用程序移动到后台时创建的

虽然这张图片的大小相对较小,但在我的真实应用程序中,它会在用户应用程序频繁切换后导致应用程序崩溃

这是同样的应用程序,同样的图像,用Swift编写,使用同样的方法创建UIRN正在使用的图像

没有额外的图像加载到内存中。RN将这些额外图像加载到内存中而不清除旧图像的做法有什么不同?当应用程序进入后台时会发生什么

更新

在标记了一代人之后,我注意到所有的大图像都来自应用程序进入后台时的iOS快照:

   0 libsystem_kernel.dylib mmap
   1 ImageIO _ImageIO_Malloc
   2 ImageIO AppleJPEGReadPlugin::copyImageBlockSet(InfoRec*, CGImageProvider*, CGRect, CGSize, __CFDictionary const*)
   3 ImageIO IIO_Reader::CopyImageBlockSetProc(void*, CGImageProvider*, CGRect, CGSize, __CFDictionary const*)
   4 ImageIO IIOImageProviderInfo::CopyImageBlockSetWithOptions(void*, CGImageProvider*, CGRect, CGSize, __CFDictionary const*)
   5 CoreGraphics CGImageProviderCopyImageBlockSetWithOptions
   6 QuartzCore CA::Render::copy_image(CGImage*, CGColorSpace*, unsigned int, double, double)
   7 QuartzCore CA::Render::prepare_image(CGImage*, CGColorSpace*, unsigned int, double)
   8 QuartzCore CA::Layer::prepare_commit(CA::Transaction*)
   9 QuartzCore CA::Context::commit_transaction(CA::Transaction*, double)
  10 QuartzCore CA::Transaction::commit()
  11 UIKitCore __83-[UIApplication _createSnapshotContextForScene:withName:performLayoutWithSettings:]_block_invoke_4
  12 UIKitCore -[UIApplication _performWithUICACommitStateSnapshotting:]
  13 UIKitCore __83-[UIApplication _createSnapshotContextForScene:withName:performLayoutWithSettings:]_block_invoke_2
  14 UIKitCore +[UIView(Animation) performWithoutAnimation:]
  15 UIKitCore __83-[UIApplication _createSnapshotContextForScene:withName:performLayoutWithSettings:]_block_invoke
  16 UIKitCore -[UIScene _applyOverrideSettings:forActions:]
  17 UIKitCore -[UIWindowScene _applySnapshotSettings:forActions:]
  18 UIKitCore -[UIApplication _createSnapshotContextForScene:withName:performLayoutWithSettings:]
  19 UIKitCore __65-[UIApplication _performSnapshotsWithAction:forScene:completion:]_block_invoke_3
  20 FrontBoardServices -[FBSSceneSnapshotAction _executeNextRequest]
  21 FrontBoardServices -[FBSSceneSnapshotAction _executeNextRequest]
  22 FrontBoardServices -[FBSSceneSnapshotAction executeRequestsWithHandler:completionHandler:expirationHandler:]
  23 UIKitCore __65-[UIApplication _performSnapshotsWithAction:forScene:completion:]_block_invoke_2
  24 UIKitCore -[UIApplication _beginSnapshotSessionForScene:withSnapshotBlock:]
  25 UIKitCore __65-[UIApplication _performSnapshotsWithAction:forScene:completion:]_block_invoke
  26 UIKitCore -[UIScene _enableOverrideSettingsForActions:]
  27 UIKitCore -[UIScene _performSystemSnapshotWithActions:]
  28 UIKitCore -[UIApplication _performSnapshotsWithAction:forScene:completion:]
  29 UIKitCore __98-[_UISceneSnapshotBSActionsHandler _respondToActions:forFBSScene:inUIScene:fromTransitionContext:]_block_invoke_3
  30 UIKitCore __98-[_UISceneSnapshotBSActionsHandler _respondToActions:forFBSScene:inUIScene:fromTransitionContext:]_block_invoke.30
  31 UIKitCore -[UIApplication prepareSnapshotsWithAction:forScene:completion:]
  32 UIKitCore __98-[_UISceneSnapshotBSActionsHandler _respondToActions:forFBSScene:inUIScene:fromTransitionContext:]_block_invoke_2
  33 UIKitCore -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:]
  34 UIKitCore -[UIScene scene:didUpdateWithDiff:transitionContext:completion:]
  35 UIKitCore -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:]
  36 FrontBoardServices -[FBSSceneImpl updater:didUpdateSettings:withDiff:transitionContext:completion:]
  37 FrontBoardServices __88-[FBSWorkspaceScenesClient sceneID:updateWithSettingsDiff:transitionContext:completion:]_block_invoke_2
  38 FrontBoardServices -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:]
  39 FrontBoardServices __88-[FBSWorkspaceScenesClient sceneID:updateWithSettingsDiff:transitionContext:completion:]_block_invoke
  40 libdispatch.dylib 0x102a9b2a7
  41 libdispatch.dylib 0x102a9e9cf
  42 FrontBoardServices __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__
  43 FrontBoardServices -[FBSSerialQueue _queue_performNextIfPossible]
  44 FrontBoardServices -[FBSSerialQueue _performNextFromRunLoopSource]
  45 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
  46 CoreFoundation __CFRunLoopDoSource0
  47 CoreFoundation __CFRunLoopDoSources0
  48 CoreFoundation __CFRunLoopRun
  49 CoreFoundation CFRunLoopRunSpecific
  50 GraphicsServices GSEventRunModal
  51 UIKitCore UIApplicationMain
  52 tmp main /...
  53 libdyld.dylib start


啊,当然,当应用程序进入后台时,操作系统实际上会拍摄应用程序的图片,在后台应用程序中滚动时,该图片会用作预览。在我们的应用程序中,我们执行以下操作:

- (void)deleteAllTemporaryFiles
{
  RCTLogInfo(@"[Delegate] Deleting all temp files...");
  [self deleteDirectoryFiles:NSTemporaryDirectory()];
  [self deleteDirectoryFiles:NSSearchPathForDirectoriesInDomains(NSCachesDirectory,   NSUserDomainMask, YES)[0]];
  [self deleteDirectoryFiles:NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]];
}

- (void)deleteDirectoryFiles:(NSString *)directory
{
  NSArray<NSString *> *temp = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directory error:NULL];
  for (NSString *path in temp) {
    if (/* check for directories you want to keep here */) continue;
    @try {
      NSString *filePath = [directory stringByAppendingPathComponent:path];
      RCTLogInfo(@"[Delegate] Deleting %@",filePath);
      [[NSFileManager defaultManager] removeItemAtPath:filePath error:NULL];
    }
    @catch (NSException *e) {
      RCTLogInfo(@"[Delegate] Deletion error: %@", e);
    }
  }
}

尝试在组件外部声明
const IMAGE=require('./test.png')
,然后由
使用,可能多次重新渲染会导致内存泄漏。刚刚尝试过,我仍然看到相同的行为。哦,值得一试,可能尝试删除安全视图包装,但没有SafeAreaView恐怕也不走运
// Delete all temp files when app is paused
- (void)applicationDidEnterBackground:(UIApplication *)application
{
  [self deleteAllTemporaryFiles];
}