Sfoglia il codice sorgente

Fix memory issue for large file in Share ext.

Use ImageIO to preserver memory.
Share extension doesn't use `assetLocalIdentifier` so it isn't necessarily needed there. Only for files.. but might be a memory issue to investigate..

Signed-off-by: Henrik Storch <henrik.storch@nextcloud.com>
Henrik Storch 3 anni fa
parent
commit
6e0e25b62a

+ 2 - 2
Share/NCShareCell.swift

@@ -46,8 +46,8 @@ class NCShareCell: UITableViewCell {
         imageCell?.layer.cornerRadius = 6
         imageCell?.layer.masksToBounds = true
 
-        if let image = UIImage(contentsOfFile: (NSTemporaryDirectory() + fileName)) {
-            imageCell?.image = image.resizeImage(size: CGSize(width: 80, height: 80), isAspectRation: true)
+        if let image = UIImage.downsample(imageAt: URL(fileURLWithPath: NSTemporaryDirectory() + fileName), to: CGSize(width: 80, height: 80)) {
+            imageCell.image = image
         } else {
             if !resultInternalType.iconName.isEmpty {
                 imageCell?.image = UIImage(named: resultInternalType.iconName)

+ 31 - 0
iOSClient/Extensions/UIImage+Extensions.swift

@@ -173,4 +173,35 @@ extension UIImage {
         UIGraphicsEndImageContext()
         return newImage
     }
+
+    /// Downsamles a image using ImageIO. Has better memory perfomance than redrawing using UIKit
+    ///
+    /// - [Source](https://swiftsenpai.com/development/reduce-uiimage-memory-footprint/)
+    /// - [Original Source, WWDC18](https://developer.apple.com/videos/play/wwdc2018/416/?time=1352)
+    /// - Parameters:
+    ///   - imageURL: The URL path of the image
+    ///   - pointSize: The target point size
+    ///   - scale: The point to pixel scale (Pixeld per point)
+    /// - Returns: The downsampled image, if successful
+    static func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat = UIScreen.main.scale) -> UIImage? {
+
+        // Create an CGImageSource that represent an image
+        let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
+        guard let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions) else { return nil }
+
+        // Calculate the desired dimension
+        let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
+
+        // Perform downsampling
+        let downsampleOptions = [
+            kCGImageSourceCreateThumbnailFromImageAlways: true,
+            kCGImageSourceShouldCacheImmediately: true,
+            kCGImageSourceCreateThumbnailWithTransform: true,
+            kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels
+        ] as CFDictionary
+        guard let downsampledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions) else { return nil }
+
+        // Return the downsampled image as UIImage
+        return UIImage(cgImage: downsampledImage)
+    }
 }

+ 2 - 2
iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift

@@ -455,8 +455,8 @@ extension NCCreateFormUploadConflict: UITableViewDataSource {
 
                 do {
                     if metadataNewFile.classFile ==  NCCommunicationCommon.typeClassFile.image.rawValue {
-                        let data = try Data(contentsOf: URL(fileURLWithPath: filePathNewFile))
-                        if let image = UIImage(data: data) {
+                        // preserver memory especially for very large files in Share extension
+                        if let image = UIImage.downsample(imageAt: URL(fileURLWithPath: filePathNewFile), to: cell.imageNewFile.frame.size) {
                             cell.imageNewFile.image = image
                         }
                     }