12

According to Apple's App Extension Programming Guide:

Memory limits for running app extensions are significantly lower than the memory limits imposed on a foreground app. On both platforms, the system may aggressively terminate extensions because users want to return to their main goal in the host app. Some extensions may have lower memory limits than others: For example, widgets must be especially efficient because users are likely to have several widgets open at the same time.

App Extension has a very strict memory Constraint, and vary from each other.

What's the maximum memory budget for each type of App Extension?
Can I test them like iOS App ios app maximum memory budget?

Community
  • 1
  • 1
wj2061
  • 6,778
  • 3
  • 36
  • 62
  • 1
    There is no set memory budget for an app extension. The amount of memory an extension may consume is tied to other processes who also use memory. For example I've had widgets who got terminated while they were using around 4000 rpages (16mb), and other times they got terminated while they were using 1000 rpages. The foremost reason why these widgets got terminated were not because they were using up too much memory, but because they were not able to free up memory when the OS asked for it. – Sander Saelmans May 21 '16 at 13:27
  • I've had an iMessage app extension that's getting terminated on iPhone X at about 100 MB usage, with system showing 200 MB+ free. At least I think that's why it's exiting. – drewster Mar 12 '18 at 19:22

3 Answers3

5

I just encounter on iPad Pro 9.7 a crash with message:

Thread 1: EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=120 MB, unused=0x0)

So it is 120 MB on a 2GB iOS device, but note that, limit differs based on type of extension.

Example:

Apple confirmed the 5-6MB memory limit for network extensions, raised to 15MB since iOS 10 Beta 2. These limits are insufficient for some Apps (see Psiphon3 ticket).

Testing a VPN (Network Extension's NEPacketTunnelProvider) produced below error:

Thread 1: EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=15 MB, unused=0x0)
Top-Master
  • 7,611
  • 5
  • 39
  • 71
Owen Zhao
  • 3,205
  • 1
  • 26
  • 43
  • 1
    My today extension crashes at 26 MB on an iPad 6th gen – Emma Labbé Feb 04 '19 at 14:13
  • @ColdGrub1384 Had the same problem. in my code it was assigning image assets to UIImageView in storyboard. This was increasing storyboard binary size. Had removed it and assigned images in the code. solved the crash – toxicsun Feb 18 '19 at 11:11
  • Same problem here when adding an overlay to a grabbed image with crashing for anything over 8-10mb. But, no assigning it to a UIImageView but creating a UIImage with a graphic context and it crashes at drawInRect.vImage`_ERROR_Buffer_Write__Too_Small_For_Arguments_To_vImage__CheckBacktrace: – user1139479 Apr 01 '19 at 13:44
  • How can we release the memory when we close the extension ? In my case whenever i open extension it keep increase the memory and when i open at 5th time , it crash and say memory limit exceeds – Anita Nagori Mar 12 '21 at 21:45
  • It must be memory leaks in your extension. Check your own code. – Owen Zhao Mar 13 '21 at 03:19
1

In my case I tried to display a 5500 x 3000 px image in a UIImageView and it crashes(EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=120 MB, unused=0x0)) on iPhone SE but not on the simulator.

Running memory profile helps to figure out the issue. Downsize the image before assigning to UIImageView.image fixed the issue.

Bill Chan
  • 3,199
  • 36
  • 32
  • Because I also had issues in an extension. Always remember that the RAM limit is not enforced on the simulator. – voidStern Apr 24 '20 at 15:09
0

I was trying to create a thumbnail from a shared image via extension and saw that when loading an UIImage from url provided by NSItemProvider and then creating a thumbnail via:

UIGraphicsImageRenderer(bounds: thumbnailBounds).image { context in
   image.draw(in: thumbnailBounds)
}

Would cause memory overflow on the extension (>120mb) for larger images. The solution for me was to downsample the image before creating an UIImage directly from the url to a reasonable size in pixels for my app so it was manageable by the share extension without causing a memory overflow.

private func resizeForUpload(_ imageURL: URL) -> UIImage? {
    let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
    let maxDimensionInPixels: CGFloat = 2000
    let downsampleOptions = [kCGImageSourceCreateThumbnailFromImageAlways: true,
                                     kCGImageSourceShouldCacheImmediately: true,
                               kCGImageSourceCreateThumbnailWithTransform: true,
                                      kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as CFDictionary
    
    guard let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions), let downsampledImage =  CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions) else {
        return nil
    }
    
    return UIImage(cgImage: downsampledImage)
}

This is the way to use private func resizeForUpload(_ imageURL: URL) -> UIImage?

if itemProvider.hasItemConformingToTypeIdentifier(SystemUTType.image) {
        itemProvider.loadItem(forTypeIdentifier: SystemUTType.image, options: nil) { secureCoding, error in
            if let url = secureCoding as? URL,
               let image = self.resizeForUpload(url) {
                // The iOS Photos app comes here.
                completion(image, nil)
            } else if let image = secureCoding as? UIImage {
                // The iOS screenshot editor comes here.
                // The iOS Notes app comes here.
                completion(image, nil)
            } else if let data = secureCoding as? Data,
                       let image = UIImage(data: data) {
                completion(image, nil)
            } else {
                completion(nil, error)
            }
        }
Ramon Vasconcelos
  • 1,466
  • 1
  • 21
  • 28