Save yourself from spending hours on screenshots for the App Store. Here's a step-by-step guide on how you automate the process of taking screenshots for all supported screen sizes and languages.
Automate Screenshots for App Store Using Fastlane

Written by
In my last post, I shared with you the source code for an app called QCards that I released on the App Store. The screenshots that went on the App Store were all generated using Fastlane. In this post, we'll go over how I went about generating them.
Here's why you shouldn't create screenshots for the App Store manually. Imagine your want four different screenshots to preview you app. But you also support four different languages. And not to mention, you support both iPhone and iPad which is three screen sizes in total (iPhone 5.5", 6.5" and iPad Pro).
4 previews x 4 languages x 3 screen sizes = 48 screenshots 😱
And get ready to repeat the process each time you change the layout of the app. So let's instead automate this.
Initializing Fastlane
The first thing you need to do is to install Fastlane if you haven't already. Open your terminal and run this command: sudo gem install fastlane -NV
.
Next up, navigate to the directory of your project. From here, you want to run fastlane snapshot init
which will create two files, Snapfile and SnapshotHelper.swift, for you.
Create a new folder in the root of your project folder. Call it "fastlane" and move Snapfile into the folder.
UI Test Target
What you want to do now is to add a UI Testing Bundle target to your project.
Give the target a name. You could call it "FastlaneSnapshot".
Now, you need to move the SnapshotHelper.swift file to this newly created target. Make sure to update the target membership of this file to FastlaneSnapshot.
UI Test Scheme
Add a new scheme called "FastlaneSnapshot". Make sure to select the UI Test target here.
Once you've done that, go to Edit Scheme -> Build
. Make sure to give it the following settings:
Also, make sure to check off the Shared
option.
Update Snapfile
Open up the Snapfile and update it to your needs, including the scheme to "FastlaneSnapshot". Here's how it could look:
# Uncomment the lines below you want to change by removing the # in the beginning # A list of devices you want to take the screenshots from devices([ "iPhone 11 Pro Max", "iPhone 8 Plus", "iPad Pro (12.9-inch) (3rd generation)" ]) languages([ "en-US" ]) # The name of the scheme which contains the UI Tests scheme("FastlaneSnapshot") # Where should the resulting screenshots be stored? output_directory("./fastlane/screenshots") # remove the '#' to clear all previously generated screenshots before creating new ones clear_previous_screenshots(true) # Arguments to pass to the app on launch. See https://docs.fastlane.tools/actions/snapshot/#launch-arguments # launch_arguments(["-favColor red"]) # For more information about all available options run # fastlane action snapshot
Now we are set up and ready to take the actual screenshots of the app.
Take the screenshots
What you need to do is write UI tests that navigate through the screens you want to capture. I won't go over how this works in this post, but it's not too difficult to figure out. Make sure to check out the code from my QCards app here for inspiration.
The entry point for Fastlane is a test function called testGenerateScreenshots
that you need to provide. From here, you can navigate your app as you like. I usually split navigation between my screens up in several functions that I call from testGenerateScreenshots
to keep it slim and readable.
What's provided by the SnapshotHelper.swift file is a function func snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20)
. You call this throughout your UI tests, whenever you want to capture a screenshot. It could look something like snapshot("LoginScreen")
.
Here's an example of the snapshot
function in action:
import XCTest let deckTitle = "My presentation" let cardTitle = "First topic" let cardContent = "Here are some very important points" class FastlaneSnapshot: XCTestCase { override func setUp() { super.setUp() continueAfterFailure = false let app = XCUIApplication() setupSnapshot(app) app.launch() } func testGenerateScreenshots() { let app = XCUIApplication() app.navigationBars["QCards"].buttons["createDeckButton"].tap() let deckTitleField = app.textFields["deckTitleTextField"] deckTitleField.tap() deckTitleField.typeText(deckTitle) app.buttons["addButton"].tap() snapshot("AllDecks") createCard() } func createCard() { app.tables.staticTexts[deckTitle].tap() app.navigationBars[deckTitle].buttons["addButton"].tap() let cardTitleTextField = app.textFields["cardTitleTextField"] cardTitleTextField.tap() cardTitleTextField.typeText(cardTitle) let cardContentTextView = app.textViews["cardContentTextView"] cardContentTextView.tap() cardContentTextView.typeText(cardContent) snapshot("CreateCard") } }
Running the tests won't capture the screenshots. What you need to do is to open your terminal, navigate to the fastlane folder inside your project and run fastlane snapshot
. This will create a screenshots folder inside the fastlane folder, containing all of your captured screenshots.
Conclusion
That was it! A great way to automate a tedious task that would otherwise cost you several hours now and each time you change your layout of your app. It doesn't take long to setup and grab the screenshots you need, so there’s no reason to hold back!
In the next post, we'll go over how you automate framing you screenshots, adding a background and localized texts.
If you haven't done so already, check out the source code for the QCards app on GitHub.
Share this post
Facebook
Twitter
LinkedIn
Reddit
You may also like

DevOps
Architecting a Feature Toggle Service for iOS Apps
Feature toggling is essential for keeping your apps flexible in production. Sometimes you want to try ideas fast to see if they stick. Maybe you want to split test two ideas and see what performs the best. Whatever the case may be, the feature toggling service should be highly scalable and not be a bottleneck in your workflow. Here’s how you create a feature toggling service with a clean iOS architecture.

Automation
How to Generate API Client Code in React (Native) Apps
Keeping your API client code updated whenever there’s a change in the back-end rest apis and models is tedious and error prone as a front-end developer. A better way would be if the API client code was kept updated automatically so you have one less thing to worry about.

Automation
Continuous Integration Using GitHub Actions for iOS Projects
Github Actions are finally publicly released! It’s an opportunity to easily enable continuous integration in your projects on GitHub, so here’s how you set it up for your iOS projects to perform automated code validation and testing on pull requests.