Automatically Delete iOS Simulator Screenshots

In iOS Development, you'll often use Command + S to take screenshots of your app running in the iOS Simulator. Although this is very convenient for sharing screenshots of your application with your team, or for pull requests, etc., since the system saves these screenshots to your Desktop, it quickly leads to a cluttered digital workspace.

In this article, we'll take a look at a quick script you can use that will automatically delete any Simulator screenshot that hasn't been opened or modified in the last 14 days.


Writing The Script

This approach relies on daemons - pronounced "demons"-  which are effectively scripts that run autonomously in the background and are not under the control of a user or another application.

💡
For more information about daemons and their implementation, see this earlier blog post I wrote.

We'll return to the topic of daemons shortly, but let's write out the Python script first.

#!/usr/bin/python3

import os, time, shutil

two_weeks_ago = time.time() - (1 * 86400)
root = "/Users/aryamansharda/Desktop"

for i in os.listdir(root):
    path = os.path.join(root, i)

    if os.stat(path).st_mtime <= two_weeks_ago:
        if os.path.isfile(path) and ("Simulator Screen Shot" in path or "Simulator Screen Recording" in path):
            try:
                os.remove(path)

            except:
                print("Could not remove file:", i)

The script simply checks all of the files at the specified path and removes any that haven't been modified in over two weeks, provided the filename contains the phrase "Simulator Screen Shot" or "Simulator Screen Recording".

💡
If you've changed the Simulator's screenshot output location or its default naming behavior for its images, you'll need to modify this script.

Configuring launchd

Now that the script is finished, let's set it up to run automatically.

MacOS's launchd framework allows us to create new daemons. If you're familiar with cron jobs, think of launchd as an equivalent on Mac.

Launchd is one of the first services or daemons as they are also known that launch when your Mac boots.

It’s a launch daemon that starts right after the kernel – the Unix core of macOS – and has a ProcessID (PID) of 0 or 1.

Its job is to load other daemons to load and run. It continues running in the background to make sure that services are still running, stops them if necessary, and launches any additional services that you need while you’re using your Mac. Your

Mac wouldn’t be able to run without it. And most of the time, it takes up very few resources.
MacPaw

In order to schedule a script with launchd, we need to create a .plist file which specifies the name of our process, the executable to launch, and at what frequency it should execute.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.AryamanSharda.SimulatorScreenshots</string>
    <key>RunAtLoad</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/python3</string>
    <string>/Users/aryamansharda/Documents/Personal/SimulatorScreenshots/RemoveOldScreenshots.py</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
    	<key>Hour</key>
        <integer>18</integer>
        <key>Minute</key>
        <integer>15</integer>
        <key>Weekday</key>
        <integer>5</integer>
    </dict>
</dict>
</plist>

Label

This is the name of the job within launchd and must be unique for each job. As you've likely already noticed, the name is written in reverse domain notation much like bundle identifiers.

This should match the name of the .plist sans the extension.

RunAtLoad

Adding this key saves us the extra step of having to start the script after we've loaded it into the Terminal.

ProgramArguments

This is an array of strings that represent the tokenized arguments and the program to run. In this case, it will first invoke a Python shell and then run our script.

StartCalendarInterval

This allows us to specify a specific time and date to run our task. In this case, the script is configured to run at 6:15 pm every Friday. Both 0 and 7 are used to represent Sunday which means Monday is a 1 and so on.

💡
There are far more options here. One could do StartInterval which would repeat a job every n seconds or RunAtLoad which would run the job the moment it's successfully loaded.

To read more about the different configuration options, check out this resource.

Setting up the script

After creating the two files from the source code above, we'll just need to make a few small changes to our system permissions.

Start by changing the permissions of the .plist and the Python script:

sudo chown root:wheel RemoveOldScreenshots.py
sudo chown root:wheel com.AryamanSharda.SimulatorScreenshots.plist
If you're curious about the wheel user group, you can read more about it here.

Then, make sure that your Python installation and Terminal both have Full Disk Access so they're able to actually delete the files.

With everything configured, our final step is to load our new agent and start it!

In the Terminal, we'll need to find our user id:

id -u
502

Next, type in the following command and hit Enter.

💡
Make sure you modify the command to use your user id and file path.
# launchctl bootstrap gui/{USER_ID} {PATH_TO_PLIST}

launchctl bootstrap gui/502 /Users/aryamansharda/Documents/Personal/SimulatorScreenshots/com.AryamanSharda.SimulatorScreenshots.plist

This will automatically install, load, and run our script since we've specified RunAtLoad to true.

If you ever want to stop the script from executing, simply run:

launchctl bootout gui/502 /Users/aryamansharda/Documents/Personal/SimulatorScreenshots/com.AryamanSharda.SimulatorScreenshots.plist

And that's a wrap! Now, our script is completely autonomous and will continue to run at whatever interval we've specified. Our Desktop will now stay neat and tidy without any manual intervention 😊.


If you're interested in more articles about iOS Development & Swift, check out my YouTube channel or follow me on Twitter.

If you're an indie iOS developer, make sure to check out my newsletter:

Indie Watch
Indie Watch is an exclusive weekly hand-curated newsletter showcasing the best iOS, macOS, watchOS, and tvOS apps from developers worldwide.

I feature a new developer every issue, so feel free to submit your indie iOS apps!


Do you have an iOS Interview coming up?

Check out my book Ace The iOS Interview!


Additional Resources