Published on

How to Turn Segmented Objects into iMessage Stickers with a Sticker Pack Exporter on iOS

Authors
  • avatar
    Name
    Almaz Khalilov
    Twitter

How to Turn Segmented Objects into iMessage Stickers with a Sticker Pack Exporter on iOS

TL;DR

  • You’ll build: An iOS app (with an iMessage extension) that lets you pick a photo, automatically lift its subject (foreground object) and turn it into a sticker you can send via iMessage.
  • You’ll do: Get Apple Developer access → Install Xcode + frameworks → Run a sample Sticker Pack Exporter app → Integrate the VisionKit API and iMessage extension into your own app → Test it on an iPhone (with iMessage).
  • You’ll need: Apple Developer account, an iPhone (iOS 17 or later), Xcode 15+ (with iOS 17 SDK).

1) What is Sticker Pack Exporter?

Sticker Pack Exporter is a solution that uses Apple's VisionKit and Messages frameworks to automatically create iMessage stickers from photos. It segments (isolates) the main subject of an image (for example, a person or object) and generates a PNG with a transparent background – essentially a sticker. Apple introduced the underlying subject-lifting capability in iOS 16 and expanded it in iOS 17 so users can turn photo subjects into stickers natively. Sticker Pack Exporter lets developers bring that capability into their own apps.

What it enables

  • One-tap image segmentation: Automatically extract the foreground object from an image with VisionKit's subject lifting API (returns a cut-out subject image). No manual editing needed.
  • Instant iMessage stickers: Create stickers that behave like built-in ones – you can drag and drop them onto chat bubbles in iMessage or send them inline. The stickers can appear in the iMessage app drawer and the iOS 17 Sticker keyboard for easy reuse.
  • Personalized sticker packs: Empower users to make their own sticker packs (e.g. of their pets, products, or artwork) and share them. This is great for creative expression, community engagement, or even brand promotion via messaging.

When to use it

  • User-generated content apps: If your app involves photos or creativity (e.g. a photo editor, meme maker, journaling app), adding a “create sticker” feature can delight users and encourage sharing.
  • Social and messaging features: Use it when you want to increase engagement by letting users turn moments into stickers they can send to friends. It’s more fun and personal than sending generic images.
  • Rapid sticker pack creation: For designers or marketers, this can quickly turn a batch of product images or illustrations into an iMessage sticker pack without manually removing backgrounds.

Current limitations

  • Apple ecosystem only: This solution targets iOS (Messages app). There’s no direct equivalent for Android’s default SMS/MMS apps since iMessage stickers are proprietary to Apple’s ecosystem. (On Android, you’d have to integrate with apps like WhatsApp for stickers – more on that later.)
  • Device/OS requirements: Subject lifting requires iOS 17+ for the VisionKit API. It will not work on earlier iOS versions unless you implement a custom Core ML model. Also, very high-resolution images might be downscaled for processing (VisionKit's out-of-process analysis limits image size for performance).
  • Sticker format constraints: iMessage sticker images must be PNG, APNG, GIF, or JPEG and under 500 KB. They also have fixed dimensions – between 100×100 and 206×206 points (at @3x, that's up to 618×618 px). You may need to resize or compress generated stickers to meet these specs.
  • No programmatic sticker library access: iOS 17 allows users to create personal “Live Stickers” that persist in the keyboard’s sticker drawer, but apps cannot directly save stickers to the system collection (no public API for that). Your app can share stickers via an iMessage app extension or by sending the image, but the user must manually add it to their collection if they want it saved system-wide.
  • Content & moderation: If users create stickers in your app, remember App Store guidelines treat them as user-generated content. Plan for image content moderation if your app is publicly distributed.

2) Prerequisites

Access requirements

  • Apple Developer Account: Create or sign in to your Apple Developer account (required to run on a physical device and to deploy an iMessage app). A paid account is needed to publish on the App Store, but you can test on-device with a free account (using a personal team provisioning).
  • iMessage App ID/Provisioning: If you plan to test on device or share the sticker pack, you’ll need an App ID that includes iMessage app capabilities. In Apple’s Developer Portal or Xcode, enable the Messages App capability when configuring your App ID. (Xcode can auto-manage provisioning for you when you add the iMessage extension.)
  • (If applicable) App Groups (for data sharing): If your main app and the iMessage extension need to share data (e.g. the generated sticker images), set up an App Group. Enable the App Groups capability and register a group identifier (e.g. group.com.yourCompany.stickerExporter) for both targets App Group setup.

Platform setup

iOS (Development Environment)

  • Xcode 15 or newer with iOS 17 SDK. (Ensure your Mac is running the required macOS version for Xcode 15.)
  • Deployment device: An iPhone or iPad running iOS 17+. While the iOS Simulator can lift image subjects using VisionKit, testing the actual iMessage sending experience is best on a real device logged into iMessage.
  • Swift Package Manager/CocoaPods: Not strictly needed for Apple’s built-in frameworks. However, if you use third-party libraries or Apple’s sample code, make sure you have any package managers installed (e.g. Homebrew for tools, CocoaPods gem if needed). For our use case, Apple’s VisionKit and Vision frameworks are included in iOS – no additional SDK to install.

Android (if building a similar feature)

(iMessage stickers won’t run on Android, but if you want a cross-platform angle – such as creating WhatsApp sticker packs – you’ll need an Android setup. This section is optional and only relevant for alternate messaging platforms.)

  • Android Studio Flamingo+ / Android 13+ if targeting a sticker feature in an Android app (e.g. for WhatsApp).
  • Gradle and Kotlin (Latest stable versions) for building the Android app.
  • Device/Emulator: An Android phone or emulator. Note that WhatsApp stickers require the actual WhatsApp app or WhatsApp Business API to test integration.

Hardware or mock

  • iPhone or iPad: A physical device is recommended to fully experience sending/peeling stickers in a real Messages conversation. (Simulators cannot mimic multi-touch drag-and-drop of stickers in a chat.)
  • Camera or Photo Library access: Use your device’s camera to snap a test photo, or have some sample images in the photo library. The feature will need an image source to create a sticker from.
  • (Optional) Android test device: If you plan to experiment with other platforms (like creating a WhatsApp sticker maker on Android), have an Android device or emulator with the target messaging app installed.

3) Get Access to Sticker Pack Exporter

Because Sticker Pack Exporter uses Apple’s native frameworks, “getting access” mostly means ensuring you have the right developer setup:

  1. Enroll in Apple’s Developer Program: Make sure you have Xcode installed and are signed in with your Apple ID under Xcode > Settings > Accounts. If you have a paid developer account, use that; if not, your free account can still run apps on your own device for testing.
  2. Enable iMessage App capability: In your Apple Developer account, register an App ID for your project (if not using automatic signing). Enable the Messages Extension capability on that App ID. This tells Apple’s ecosystem your app will include an iMessage extension.
  3. Create a project in Xcode: Open Xcode and create a new iOS app project (or use an existing app). You will add an iMessage extension target to it in the next steps. Ensure the bundle identifier matches the App ID you set up, and your team (developer account) is selected in Signing & Capabilities.
  4. Request necessary entitlements: If you plan to share data via App Groups or need Photo Library access, turn those capabilities on in the project’s Signing & Capabilities tab. Xcode will handle generating a provisioning profile with those entitlements if your account is configured.
  5. Provisioning and certificates: Xcode can automatically manage signing. If doing manually, download the provisioning profile for the App ID from Apple Developer portal and install it. Ensure your development certificate is valid. (For most users, letting Xcode auto-manage is simplest.)

Done when: You have a running Xcode project with signing set up (no build errors related to provisioning). You should also see, in the Apple Developer portal (Certificates, Identifiers & Profiles), your App ID with the iMessage extension and any App Group listed. Essentially, you’re ready to build and run the sample on a device with the proper entitlements (e.g. it can access photos and the Messages app).


4) Quickstart A — Run the Sample App (iOS)

Goal

Run a provided sample app to verify that segmenting an object and sending it as a sticker works on your device (or simulator). This sample will demonstrate the end-to-end feature: selecting a photo, extracting the subject, and displaying it in an iMessage extension for sending.

Step 1 — Get the sample

  • Option 1: Clone the repo. We’ve prepared a sample Xcode project called StickerExporterSample. Clone it from the repository (for example, via git clone https://github.com/your-org/StickerExporterSample.git). Open the Xcode workspace/project.
  • Option 2: Download the project ZIP. If you don’t have Git, download the project as a ZIP from the repository page. Unzip it and open the .xcodeproj or .xcworkspace in Xcode.

The project contains two targets: the iOS app and a MessagesExtension. The extension is where the sticker pack lives.

Step 2 — Install dependencies

This sample uses only Apple frameworks, so no external package installation is required. However, a few things to check:

  • Swift packages: Open Xcode’s Package Dependencies for the project. (There should be none needed; all functionality uses VisionKit and UIKit.)
  • iOS SDK version: Make sure the Base SDK is iOS 17.0 or later (Xcode 15+ handles this). The deployment target for the app and extension is set to iOS 17 – you can adjust if needed, but iOS 17 is required for VisionKit’s subject lift API.
  • CocoaPods (if applicable): Not used in this project. If you see a Podfile (unlikely here), run pod install. Otherwise, proceed.

Step 3 — Configure app

Before running, some configuration steps:

  • Update bundle identifiers: In Xcode, select the project and verify the bundle ID for the app and the extension. If you changed it when setting up your App ID, make sure Xcode’s bundle IDs match what’s in the Apple portal. e.g. com.yourCompany.StickerExporter for the app and com.yourCompany.StickerExporter.MessagesExtension for the extension.
  • App Group setup: If the sample uses an App Group for sharing images, you’ll see a group identifier in the project’s Capabilities. Ensure you add your own App Group ID there (and that it’s added on the Apple portal). The sample’s README will note if App Groups are needed.
  • Privacy permissions: Open Info.plist of the app target. Ensure it has usage descriptions for any privacy-sensitive data:
    • NSPhotoLibraryUsageDescription – because the app will likely let the user pick a photo.
    • NSCameraUsageDescription – if there’s an option to take a photo for a sticker.
    • These strings can be generic (e.g. “We need access to your photos to create stickers from your images”). If these keys are missing, add them with appropriate text, otherwise iOS will block access at runtime.

No other special config files or API keys are required since VisionKit is built-in. Just make sure the above items are in place.

Step 4 — Run

  1. Build the app target: In Xcode’s scheme selector, choose the main app (not the extension). Select a target device or simulator (e.g. your iPhone plugged in, or an iOS 17 simulator). Hit Run ▶️.
  2. Launch the app: The app should install and launch on the device. You’ll see a simple UI (e.g. a button to pick an image and maybe a preview area). Follow on-screen instructions to choose or capture a photo.
  3. Trigger sticker creation: Using the app UI, select a photo from your library (grant permission if prompted). Then tap the “Create Sticker” (or similar) button. The app will process the image, and you should see the background disappear from the photo, leaving just the subject. This new sticker image will be saved for the iMessage extension to use.
  4. Open the Messages extension: The sample app includes an iMessage extension that should already be active. On your test device, open the Messages app. Start a new message or go to an existing conversation. You should see your app’s icon in the iMessage app drawer (the bar of app icons below the text field). Tap it to open your Sticker Pack extension.
  5. Verify sticker in extension: The extension UI will show the stickers available. It should now include the sticker you just created. (In many sample implementations, the extension reads from the shared container where the app saved the PNG.) You might see a sticker browser or a single image – depending on the design.

Step 5 — Use the sticker in a message

  • Send the sticker: Drag the sticker from the extension up into the conversation, or tap it (depending on UI) to insert it into the text field. It should appear as a sticker (with a small app icon indicating it’s from your app). Send the message as usual.
  • Confirm receipt: If you sent it to yourself or another device, check that the sticker image goes through properly. On the receiver’s end (another iOS device), the sticker should appear as an image with transparent background. (If the receiver doesn’t have your app, iMessage will still deliver the sticker – it gets sent as an image asset with your app’s identifier.)

Verify

  • Subject is correctly segmented: The sample app should show the chosen object separated from its background (e.g. only your dog/cat/person/etc is visible on a transparent or colorful backdrop). This confirms VisionKit’s subject lifting worked.
  • Sticker appears in iMessage: Opening the Messages extension shows the new sticker in the list. You can select it and it pastes into the chat.
  • Sticker sends successfully: After sending, the sticker is visible in the conversation on both sender and receiver sides, with correct transparency. It behaves like a normal sticker (you can even long-press and “peel” it onto message bubbles on the receiver side if on iOS).

Common issues

  • Sticker not showing in extension: If you don't see the sticker in the iMessage app, the sharing might have failed. Ensure the App Group is set up and the image was saved to the shared container path. A quick fix is to add logging in the app right after saving the file, and in the extension's viewDidLoad to see what files it finds. Also double-check that your extension target has the App Group capability enabled (it should match the app's group ID extension setup).
  • Provisioning errors: If Xcode gives signing errors when building the extension, you might need to log into your developer account and register the App ID for the extension or enable the App Group there. The extension’s bundle ID must be unique and included in your provisioning profile. Regenerate profiles if needed or let Xcode try to fix signing.
  • Permission denied picking image: If tapping “Choose Photo” does nothing or shows a permissions error, check that NSPhotoLibraryUsageDescription is in Info.plist and that you actually request permission using PHPicker or UIImagePickerController. On first run, it should prompt; if not, you may have missed calling the picker properly.
  • Sticker image too large: If the resulting PNG is over 500 KB, iMessage might refuse to send it. In testing, use reasonably sized images. If you absolutely need to handle large images, implement a resizing step after segmentation (e.g. scale down to within 618x618px if needed size guidelines). This ensures the sticker meets Apple's size guidelines.
  • Simulator quirks: The iMessage extension can run in the simulator, but sometimes the simulator’s Messages app may not show the extension immediately. If that happens, try killing the Messages app on the sim and relaunching, or use a real device. Also note the simulator might not have a photo library; you can drag an image into the simulator or use a placeholder.

5) Quickstart B — Run the Sample App (Android)

There is no direct iMessage equivalent on Android, but for completeness, here’s a note on creating stickers on Android (e.g., for WhatsApp).

Goal

Demonstrate a similar feature on Android by generating a sticker and adding it to WhatsApp (a popular third-party messaging app that supports custom stickers). We will use WhatsApp’s Third-Party Sticker Packs API as an example.

Step 1 — Get the sample

  • Clone the official WhatsApp Stickers sample from GitHub: git clone https://github.com/WhatsApp/stickers.git. This repository contains Android (and iOS) sample apps and the API for creating third-party sticker packs for WhatsApp.
  • Open the Android project (e.g., Android/StickerApp in Android Studio).

Step 2 — Configure dependencies

  • Gradle setup: Open the project in Android Studio. Let it download gradle wrappers and dependencies. The WhatsApp sticker sample includes a module with necessary assets and JSON metadata.
  • WhatsApp integration: You don’t need a special token for WhatsApp’s consumer app. Ensure you have WhatsApp installed on the test device. The sample code’s manifest is already configured with the intent filters and metadata that WhatsApp expects for sticker import.

Step 3 — Configure app

  • Application ID: Change the applicationId in app/build.gradle if you want a unique package. WhatsApp requires the package name to be whitelisted in the sticker manifest; the sample is already set up for the sample’s own package.
  • Sticker assets: In the sample, replace or add your PNG images in the app/src/main/assets or drawable folder as instructed by WhatsApp’s docs. Each sticker must be ≤ 100 KB (WhatsApp’s limit) and exactly 512x512 px (PNG). You also need a tray icon (96x96 px) for the sticker pack. The sample pack comes with placeholders you can swap out.
  • Metadata: Update the contents.json (for iOS) or the sticker pack metadata in Android (usually a JSON in assets or code in the sample) to include your stickers’ file names, pack name, author, etc.

Step 4 — Run

  1. Build and install: Run the sample on an Android device with WhatsApp installed. This will install the Sticker Pack app.
  2. Add to WhatsApp: The sample app will show a list of sticker packs (one pack in this case). There is usually a button like “Add to WhatsApp”. Tap it. WhatsApp will open and prompt to import the sticker pack. Confirm to add it.
  3. Verify in WhatsApp: Open a WhatsApp chat, tap the emoji/sticker icon, and find your sticker pack icon in the stickers section. Your custom stickers should be there, ready to send.

Step 5 — Use the sticker

  • Select one of your imported stickers and send it in a WhatsApp message. Verify that it appears correctly on both the sender and receiver side (transparent background, correct size).

Verify

  • Stickers visible in WhatsApp: After adding, your stickers show up in WhatsApp’s sticker picker.
  • Sticker sends correctly: Tapping a sticker sends it in the chat, and the recipient can view it (stickers are actually sent as images, so recipients don’t need the app installed).
  • Multiple stickers: If you added more than one, ensure all appear and can be sent.

Common issues

  • App not showing in WhatsApp: Make sure the sample’s app and sticker pack metadata follow the WhatsApp spec (including content provider authority and provider meta-data). If those aren’t correct, WhatsApp will ignore your app.
  • Sticker too large or wrong format: WhatsApp requires PNG stickers of specific dimensions (512x512). If your image is not exactly that size or is a JPG, it will fail to add. Resize and convert as needed.
  • Android permission errors: The sample might not need runtime permissions, but if you customize by allowing the user to pick an image and create a sticker, you’ll need READ storage permission for older Android versions. Ensure you handle that if extending the functionality.

6) Integration Guide — Add Sticker Pack Exporter to an Existing iOS App

Goal

Integrate the sticker creation feature into your own app. We’ll add the VisionKit-based subject lifting and an iMessage extension to an existing project, allowing it to generate and send stickers. By the end, your app will let users select a photo, turn it into a sticker, and send it – all within your app’s ecosystem.

Architecture

Our integration will have two parts:

  • Main iOS app: Handles image selection, processing (segmentation), and saving the output.
  • iMessage Extension: Reads the saved sticker images and presents them in Messages as a sticker browser (using MSStickerBrowserViewController).

The components interact like this:

  1. User in main app picks or captures an image → app uses VisionKit (ImageAnalyzer) to lift the subject → app saves the resulting sticker image (PNG) to a shared container.
  2. User opens iMessage and selects your app’s sticker extension → extension loads all sticker images from the shared container (including the new one) and displays them.
  3. User sends sticker → Message is delivered with the image attached (no server needed, it’s all local).

Step 1 — Install SDK / Add frameworks

iOS (Xcode Project Changes)

  • Add the iMessage extension target: In Xcode, go to File → New → Target… and choose Message Extension (or Sticker Pack Extension). Select Messages App if you want to include custom UI and logic. (If you choose “Sticker Pack” it’s static and you can’t modify it at runtime – so go with the Messages Extension for dynamic content.)

    Xcode will add a new target folder (e.g. MessagesExtension) with a MessagesViewController.swift. This is a subclass of MSMessagesAppViewController.

  • Link frameworks: The VisionKit and Vision frameworks should be linked by default (VisionKit might require adding; check your Build Settings > Linked Frameworks). In your main app target, import VisionKit where you use it. In the extension target, import Messages and UIKit for the UI.

  • Swift Packages: No external SDK is required. The functionality uses Apple’s frameworks available in iOS 17. If you plan to support iOS 17, you might integrate a Core ML model like DeepLabV3 (via CoreML or TensorFlow Lite) to do segmentation – that would involve adding a model file and code, which is beyond this basic guide.

Android (if parallel implementation)

  • Add a dependency for any image processing library if needed (for segmentation on Android, one could use ML Kit’s selfie segmentation or TF Lite model). This is optional and out of scope for iMessage specifically.

Step 2 — Add permissions and entitlements

iOS Info.plist (Main app):

  • Add NSPhotoLibraryUsageDescription – required if your app opens the photo picker. (e.g. value "App needs access to photos to create stickers.")
  • Add NSCameraUsageDescription – if you let users take a new photo to make a sticker.
  • (If saving to camera roll, also NSPhotoLibraryAddUsageDescription, but here we save to app container, not camera roll.)
  • Enable App Groups in both app and extension targets (as discussed). In each target’s Signing & Capabilities, turn on App Groups and add your group identifier. This allows the shared container for images. Without this, the extension cannot see images saved by the app.

AndroidManifest.xml (if doing Android):

  • Ensure READ_EXTERNAL_STORAGE permission if your Android implementation reads user images. (On Android 13+, use the photo picker API instead which needs no permission, or request READ_MEDIA_IMAGES permission.)
  • For WhatsApp integration, no additional permissions, but you must include the metadata and service definitions as per WhatsApp’s docs (the GitHub sample handles this).

Step 3 — Create a thin client wrapper (design your classes)

Structure your code with separation of concerns for clarity:

  • ImageSegmentationService (or VisionService): A singleton or utility class in your iOS app that wraps VisionKit's APIs. For example, it can have a method func liftSubject(from image: UIImage) -> UIImage? that returns a PNG of the subject or nil if none. Internally, this would create an ImageAnalyzer and call analyze(image:), then use analysis.subjects.first?.image subject extraction to get the cut-out. This service abstracts the ML/vision work.
  • StickerPackManager: This handles saving and loading sticker images. It knows the file path in the shared App Group container. For instance, it might save images to ~/Library/Group Containers/<group>/stickerX.png. It can also purge old stickers if needed. The manager can also communicate with the extension (e.g., via UserDefaults in App Group or by writing a “manifest” file that the extension reads).
  • PermissionsService: A small helper to check/request permissions (camera, photo library). It can present the iOS permission dialogs and call back with results. This keeps permission logic out of your view controllers.

Definition of done:

  • VisionKit is initialized and able to produce a subject image from a given input image (tested with a few samples).
  • The sticker image is saved in the shared container and the iMessage extension can access it (test by retrieving the file in the extension).
  • The extension’s UI updates (or reloads) when a new sticker is added. (This might happen by reopening the app in Messages, or you can programmatically trigger an update via a shared flag or notification.)
  • All critical errors (no subject found, file save failed, etc.) are handled gracefully – e.g. show a message to the user rather than silently failing. Logged errors should be concise for debugging.

Step 4 — Add a minimal UI screen

Design a simple interface in your app to drive the feature:

  • Image selection UI: A button “Choose Photo” that opens the image picker (PHPickerViewController is great for iOS 14+). Display a thumbnail of the selected image in an UIImageView so the user knows what they chose.
  • Sticker preview: An UIImageView or similar to show the result after segmentation (so user sees the cut-out). Possibly with a checkerboard background or a colored canvas to illustrate transparency.
  • “Make Sticker” button: Disabled until an image is selected. When tapped, it triggers the segmentation process. Show a loading indicator (e.g. UIActivityIndicator or a “Processing…” label) while VisionKit does its work (usually under a second or two).
  • Result handling: Once the sticker PNG is saved, you might show a message like “✅ Sticker added to your iMessage app!”. You could even offer a shortcut: e.g., a button “Open iMessage” that deep-links to the Messages app to immediately use the sticker. (Using Messages URL scheme might not open directly to the extension, but you can open Messages app using sms: URL as a hint.)

On the Messages extension side, the UI is often just an MSStickerBrowserViewController that automatically displays all MSSticker items. In your MessagesExtension's MessagesViewController, you can create an instance of MSStickerBrowserViewController and implement the dataSource methods to supply stickers. The StickerPackManager can help here by listing files in the shared container and creating MSSticker objects for each file URL MSSticker initialization and sticker URLs. The extension UI doesn't need a "button" – the user just selects a sticker from the grid to send.


7) Feature Recipe — Create a Photo Sticker and Send in iMessage

Goal

When the user taps a “Make Sticker” action in your app, the app will isolate the subject from the photo, generate a sticker image, and make it available in Messages. The user can then quickly send it. We want a smooth flow from image selection to sticker sent.

UX flow

  1. Select or capture image. (App displays the chosen photo.)
  2. Tap “Make Sticker.”
  3. App shows a progress state (e.g. a spinner) while processing.
  4. Sticker ready: App shows a preview of the sticker (the segmented object on transparent background). Perhaps a “Saved to Stickers!” confirmation.
  5. Use the sticker: The user opens the Messages app extension (or tap an “Open in iMessage” shortcut) to find the new sticker and drag it into the conversation. The app extension might highlight new stickers or simply show the latest one first.

Implementation checklist

  • Image selected? Ensure the user has provided an image. If not, prompt them to do so (disable the sticker-making button until an image is loaded).
  • Permissions okay? Verify photo library or camera permission was granted (the image picker usually handles this internally). If you implement a custom camera, check AVCaptureDevice authorization as well.
  • Run segmentation: Call your ImageSegmentationService.liftSubject(image) method. This might be asynchronous. Handle the callback or promise – on success, get the subjectImage. On failure (no subject or error), inform the user (“Oops, couldn’t find a main object in that image. Try a different photo.”).
  • Save the result: Take the returned subjectImage (UIImage) and save it as PNG to the shared container. Use a unique filename (e.g. timestamp or UUID). Update your StickerPackManager’s list if you track one. Confirm the file saved (error handling for disk write).
  • UI update: Show the resulting sticker in the app’s UI (e.g. in the preview image view). Users love seeing the cut-out immediately. Maybe add a fun outline or drop shadow to emphasize it’s a “sticker.”
  • Notify extension (if needed): The iMessage extension might not instantly know a new file was added. The simplest method: whenever the extension becomes active, it reads all files fresh (so if the user switches to Messages after creating a sticker, it will load it). For more dynamic updating: you could use UserDefaults in the app group to set a flag “newSticker=true” that the extension checks, or even use a distributed notification (Darwin notification) to nudge the extension. This is an advanced step – not strictly required if the user just opens the extension after creation.
  • Provide guidance to user: After making the sticker, the app can show a tooltip like “Open Messages and find your sticker under [App Name] to send it!”. This ensures the user knows what to do next. (Optionally, a button that opens Messages is user-friendly.)

Pseudocode example:

swift

Copy code

@IBAction func onMakeStickerTapped() { guard let image = selectedImage else { showAlert("Please choose a photo first.") return } // (Permission assumed granted if we have image) statusLabel.text = "Segmenting..." Task { do { let subjectImage = try await VisionService.shared.liftSubject(from: image) guard let stickerImage = subjectImage else { statusLabel.text = "No clear subject found. Try another image." return } // Save to shared container try StickerPackManager.shared.saveSticker(stickerImage) statusLabel.text = "Sticker ready! Open Messages to send it." stickerPreview.image = stickerImage // show preview in UI } catch { statusLabel.text = "Error creating sticker 😢" print("Vision error: \(error)") } } }

swift

Copy code

// In MessagesExtension (simplified) override func viewWillAppear() { super.viewWillAppear() let stickers = StickerPackManager.shared.loadAllStickers() stickerBrowserVC.reloadStickers(with: stickers) }

Explanation: The pseudocode uses async/await for VisionKit analysis. It updates UI state throughout. In the extension, whenever it appears, it loads all stickers (ensuring new ones are included).

Troubleshooting

  • Sticker image is empty or weird: If liftSubject returns nil or an empty image, the Vision algorithm might not have found a dominant subject. Log the number of analysis.subjects found. You might handle multiple subjects (e.g. pick the largest). If none, consider using an alternative approach (like prompting user to manually crop, or using Vision framework’s segmentation mask). Also ensure the image isn’t too large – extremely high-res images might be skipped; resizing to a couple megapixels before analysis can help.
  • New sticker not appearing in extension: This is usually an App Group or timing issue. Make sure you saved the image in the group's container and used the correct container path in the extension. One trick: use FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: ...) in both the app and extension to get the path – this ensures both are looking at the same location container path. If the extension still shows an old list, you may need to reload its data. You can add a button in the extension UI to "Refresh", or simply close and reopen the extension from the app drawer.
  • Expecting instant availability in keyboard: Note that unlike Apple’s built-in Live Stickers (which go to system keyboard), our stickers are tied to the app’s extension. The user must use your iMessage app to access them. Managing expectations is key: provide a clear prompt like “Sticker added! Now open the Messages app to use it.” to bridge the context for the user.
  • Memory or performance concerns: Lifting subjects is fairly quick, but if you allow any image, watch out for very large images which could be memory intensive. You might downscale the image to, say, max 2000px on a side before processing. Also, dispose of any large data (for example, if you got a CVPixelBuffer or CGImage from Vision directly). In our simple approach using VisionKit, this isn’t a big issue – the framework handles efficient processing (possibly even using the Neural Engine).

8) Testing Matrix

Test your implementation under various scenarios to ensure robustness:

← Scroll for more →
ScenarioExpected ResultNotes
Standard photo (clear subject)Subject is correctly cut out as sticker; can send in iMessage.E.g., a portrait of a single person or a product shot should work well.
Busy background / low contrastPossibly no subject detected or imperfect cut-out.Vision might fail if subject blends in. Ensure graceful failure message.
Multiple subjects in one imageEither multiple stickers or the primary subject is chosen.VisionKit usually returns multiple subjects. Decide if you use the first or allow selection of which one.
High-resolution imageSticker created, maybe downscaled internally, but should still send.Check that the output PNG < 500 KB. If not, implement resizing.
No network connectivityEverything still works (all on-device).VisionKit is on-device; no internet needed. Great for offline use.
Photo library permission deniedApp prompts user or shows error explaining why it’s needed.Test by denying permission and tapping “Choose Photo” – your app should handle it.
Using an older deviceSticker creation works, perhaps slightly slower.Devices without the Neural Engine might be slower but still should work (subject lifting falls back to CPU/GPU).
App in background during processWhen returning, either resumes or informs user to retry.If user switches app while processing, ensure no crashes. Possibly lock orientation or handle interruptions accordingly.
Stickers after app restartPreviously made stickers persist (if you intend to save them).If you want stickers to be available even after app is closed, confirm that your images remain in the app group container between sessions.
iPad compatibilityIf supported, UI adapts and stickers still send.iPads running iPadOS 17 can also use iMessage apps. Test the UI layout in iPad, if applicable (maybe ensure no fixed iPhone-specific UI assumptions).

(Not all scenarios will apply to every implementation, but it’s good to think through these before shipping.)


9) Observability and Logging

Adding logging and analytics will help you monitor usage and diagnose issues in the wild:

  • Event logging: Instrument key events in the sticker creation flow:
    • photo_selected (with metadata like source type: camera or library),
    • segmentation_start and segmentation_complete (you could log how long it took, perhaps using os_signpost or just timestamps).
    • sticker_saved (include size of file, to watch for any that exceed limits).
    • sticker_sent (if you can detect when a sticker is sent – this is tricky because the sending happens in Messages app, but you might infer it if your extension code runs or via app becoming active again).
  • Error logging: Whenever Vision returns an error or no subject, log an event like segmentation_failed with reason if available. Similarly, log save_failed if writing file throws an error. These can be sent to your analytics or crash reporting for debugging.
  • App extension logging: Use os_log in the Messages extension to log user actions (e.g., extension_openedsticker_list_loaded(count:n)). If a user reports “I created a sticker but don’t see it in Messages,” these logs can help determine if the extension loaded the list correctly.
  • Performance metrics: If you have many users, measuring how long subject lifting takes on average (segmentation_ms) could be interesting, as well as the average size of generated stickers. If you see some devices taking much longer, it could indicate older devices or something to optimize.
  • UI feedback for logging: For development, you can include a debug label in the UI to print steps (e.g., “Saved sticker to path X”). Remove or hide this in production, but during testing it’s useful to literally see the state changes.

Remember to avoid logging sensitive data (the images themselves or any personal info in them). Stick to high-level events and perhaps image dimensions or processing time. If using a third-party analytics SDK, check their privacy guidelines since users might create personal images.


10) FAQ

  • Q: Do I need the latest iPhone or iOS version to use this?

    A: You’ll need iOS 17 or later on your device for the VisionKit subject lifting API to be available. Any iPhone or iPad that supports iOS 17 will work – for example, iPhone XS/XR and above. Newer devices (with A14 Bionic or later) may process the image faster due to the Neural Engine, but there’s no exclusive hardware requirement beyond iOS 17 support.

  • Q: What about users on older iOS versions?

    A: If your app needs to support, say, iOS 15 or 16, the built-in subject lift API won’t be there. You have a couple of options: (1) Use a Core ML model like DeepLabV3 or U2Net embedded in your app to perform background removal (this increases app size and complexity but can work offline), or (2) gracefully disable the sticker feature on unsupported OS versions (e.g., hide the “Make Sticker” button and explain it requires iOS 17+).

  • Q: Which devices can receive the stickers I send?

    A: iMessage stickers are essentially images, so any iOS device will display them. If you send a sticker to someone on iOS 17, it appears as a sticker. If the recipient is on macOS or an older iOS, they’ll see it as an image (possibly with a little app icon). Non-Apple devices (Android phones) cannot receive iMessages at all, so they won’t get the sticker unless you send it via another platform. For maximum reach, you could add a fallback “Share as image” option to send the sticker PNG via other channels (SMS/MMS, WhatsApp, etc.).

  • Q: Can I ship this feature to App Store? Any review concerns?

    A: Yes, you can absolutely ship it. Apple allows apps with Messages extensions – you just have to comply with the usual guidelines (no objectionable content, etc.). Since users can create their own stickers, your app is enabling user-generated content; make sure to have a moderation plan or disclaimers if necessary (similar to how meme or image sharing apps do). Also, test thoroughly – Apple reviewers will test the extension and the main app. One thing to note: if your app’s primary function is creating a sticker pack, Apple may categorize it under the Stickers category on the App Store. Ensure your App Store listing makes it clear what the feature is.

  • Q: The iOS 17 Photos app can make stickers with cool effects (like white outline, comic style). Can my app do that?

    A: Apple's built-in sticker creator offers those effects (outline, comic, puffy, shiny), but there's no public API to apply the same "sticker effects." You would have to replicate them manually: for example, to add a white outline, you can use Core Image or draw a stroke around the extracted image. For a comic or shiny effect, that's non-trivial – it involves shaders or image filters that Apple hasn't open-sourced. In short, you can create the raw sticker (PNG with transparency) and perhaps add a basic outline or shadow. Anything beyond that, you'd be custom-building – doable but advanced.

  • Q: Can I animate the stickers or use Live Photos?

    A: If the user selects a Live Photo, Apple's Messages will actually animate it if sent as a sticker it becomes an APNG. In our custom workflow, we don't automatically get animation frames from VisionKit – it gives a static image of the subject. To support animated stickers, you'd need to extract frames from a video or Live Photo and build an APNG/GIF yourself. This is complex and out-of-scope for most apps. If you foresee a need for animated stickers, a workaround is to let users pick a short video or Live Photo and then integrate a library to convert that to an animated PNG after removing background for each frame. Keep in mind the 500 KB size limit – animations must be short or low-res to fit.

  • Q: Can my iMessage extension send stickers programmatically without user drag/drop?

    A: Not really. Apple’s Messages framework doesn’t allow automatically sending a sticker or message – the user must perform the send action. Your extension can pre-compose a message (for example, inserting an MSSticker into the conversation via the activeConversation.insert() method), but the user still has to hit the send button. This is by design, to prevent spammy behavior. So you can streamline by adding a “Tap to add” in your extension, but sending is ultimately user-controlled.

  • Q: How do I remove stickers or manage the list?

    A: If you want to allow users to delete created stickers from the pack, you’ll need to implement that yourself (for example, a “Manage stickers” screen in the app, which deletes the image file from the shared container and perhaps notifies the extension to reload). Apple doesn’t auto-remove anything. If the list grows, consider a limit or an interface for cleanup.

  • Q: Could I use this to create a standalone sticker pack app (with pre-made stickers)?

    A: Yes, if you remove the dynamic creation part, you can bundle static images in the Messages extension (or even just create a Sticker Pack App without code). But the whole point of this guide is the dynamic aspect. For a static pack, Apple’s documentation and templates might be simpler. However, you can certainly use parts of this solution to dynamically generate those images and then ship them as built-in assets in a future update of your app.


11) SEO Title Options

  • “How to Build an iOS Sticker Pack Exporter to Turn Photos into iMessage Stickers”
  • “Create Custom iMessage Stickers from Photos using VisionKit (iOS 17 Tutorial)”
  • “Turning Segmented Objects into iMessage Stickers – A Step-by-Step Developer Guide”
  • “iOS Quickstart: Export Photo Cut-outs as iMessage Sticker Pack”
  • “VisionKit and iMessage Extension: Auto-Generate Stickers from Images on iPhone”

(These titles target keywords like iMessage stickers, custom stickers, iOS 17 VisionKit, etc., for better SEO.)


12) Changelog

  • 2025-12-25 — Verified with Xcode 15.2 and iOS 17.2 on iPhone 14. Sticker creation and sending flow tested. Updated WhatsApp sample info for Android (WhatsApp v2.23).
  • 2023-09-20 — Initial implementation on iOS 17 release: basic VisionKit integration and Messages extension setup.
  • 2023-06-05 — WWDC23: Learned about new VisionKit SubjectLift API WWDC session and animated highlights, started prototyping the feature during iOS 17 beta.