Reduce share extension crashes from your app with this one weird trick!

Tim Johnsen
iOS App Development
3 min readDec 16, 2022

--

My app Close-up lets people capture daily selfies and create time lapse videos and animated GIFs from them. Naturally, the ability to share these photos, videos, and GIFs is core functionality the app provides. I’m a big believer in UIActivityViewController (aka the “share sheet”), so that’s what powers sharing in Close-up and my other apps.

For years now I’ve noticed that sharing photos from Close-up to particular share extensions would trigger a crash. This isn’t uncommon when using the share sheet since extensions are heavily memory constrained. I’ve always kind of just blamed it on the OS memory limit or those share extensions and ignored the issue.

Tweetbot and Toot’s share extensions crashing shortly after launching

A few weeks ago I decided to see if I could work around this.

I started off by assuming the issue was related to the image being shown onscreen in these extensions. I went down the rabbit hole of implementing some more niche APIs that UIActivityItemSource provides assuming the thumbnailing would cause those extensions to stop running out of memory. Alas, at the end of this there was no difference, those extensions still crashed. Bummer.

After this it occurred to me that, despite videos and GIFs being much larger than images, the third party share extensions in question had no issues when receiving those data types.

The same extensions seem to handle huge (~30MB) videos and GIFs with no trouble at all

The main difference between how Close-up shares photos and videos/GIFs is that photos are shared as UIImage objects whereas videos and GIFs are shared as NSData. I tried sharing images as NSData instead of UIImages and Eureka! No more crashes!

Huzzah!

Turns out this is all it took:

This is highly speculative, but what I think is happening here is that when certain extensions receive UIImages they convert them to NSData and keep that data in memory to upload. Because of this, that data counts towards the extension’s very low memory limit. By passing NSData to the extension instead the data counts towards my app instead of the extension. The improved performance could also be related to memory mapping, since the data I’m passing is from files on disk.

A few days later I was talking to my friend Dave about his app Delayte. He mentioned that he was doing a bunch of work to downscale images when sharing to Messenger because it would always crash. This sounded familiar, so I told him about my discovery of passing image data instead of image objects. Later that night he gave it a try, and it seems to work for his product as well!

So, tl;dr — pass images as NSData instead of UIImages to UIActivityViewController to reduce share extensions crashing.

--

--

Tim Johnsen
iOS App Development

iOS developer at Retro.app. Previously Patreon, Instagram, Pinterest, Flipboard. Creator of Opener, Close-up, and other apps.