How to easily move iOS Simulator data files after Xcode upgrade

If you maintain an app like ConnectStats that has a lot of local files on the device and does not rely on the cloud constantly for input, each time Xcode upgrade all the iOS Simulator starts empty again and loose all the files from the previous version.

The iOS simulator keep it’s file in some complicated folder structure and the folder change each time you start it, so it can be quite tricky to locate the files. And so quite painful to locate all the folder for the previous and new version and move all the files over.

I’ll go over the solution I use in this post, using a small cli tool I wrote

Finding the Simulator Folders

In the past, I maintained Simulator Data Finder to help me easily locate these files. Since then I stopped using it because the current version of simctl provided by Apple lets you easily find the folder for a currently running app in the simulator, with the following command applied to connectstats:

xcrun simctl get_app_container booted data

It is then very easy to wrap this into a shell function to have quick access from the terminal like below

function simcd () {
  cd $(xcrun simctl get_app_container booted $1 data)

This works great and I am now using that all the time for development instead of my old app Simulator Data Finder. But when Xcode upgrades this function does not find the previous version simulators, so I then had to revert back to Simulator Data Finder, and manually copy all the files.

Now that I was so used to simctl and the simple wrapper simcd I felt the need to get a better solution for moving the files from one version to the other.

Finding old simulator directories

To find apps in old simulator, I used to the same trick I had used in Simulator Data Finder by adding a small snippet to the start of the app that saves a small hidden file in the document folder that we can then search in the file system to locate the document folder of that app. A header file can be found here for objective c or here for swift. The logic is the same for both, here is the swift implementation

func RZSimNeedle() {
    let needlePath = NSSearchPathForDirectoriesInDomains( .DocumentDirectory, .UserDomainMask, true)
    let documentsDirectory = needlePath[0] as String
    let bundleIdentifier = NSBundle.mainBundle().bundleIdentifier
    if (bundleIdentifier != nil) {
        let needle = documentsDirectory + "/.simneedle." + NSBundle.mainBundle().bundleIdentifier!
        NSData().writeToFile(needle, atomically: true)

You can then easily write code that will locate the document directory. I wrote a python utility that leverage this file to automate some workflow around upgrade of the simulator.

Moving files from old to new Simulator

You can find the utility along my other quick tools here. Beside a few help command to find information and details about existing simulator and apps container. The core command to run to upgrade app containers to new version is upgrade

This will print a report for all the app and simulator version it finds along with the command to run to mv all the file from one version to the other. The output will look like this

iPhone 11 Pro Max has app to upgrade
     iOS 13.3[Feb 2020: 4]
     iOS 13.4[Apr 2020: 5]
iPhone SE (2nd generation) has app to upgrade
     iOS 13.5[Jul 2020: 5]
     iOS 14.0[Jul 2020: 5]
iPad Pro (11-inch) (2nd generation) has app to upgrade
     iOS 13.4[May 2020: 57]
    *iOS 14.0[Oct 2020: 1]
    >iOS 14.2[Nov 2020: 324]
Command to execute:

find /Users/brice/Library/Developer/CoreSimulator/Devices/0C6A55F6-61DC-40C7-852D-AD6C019640C1/data/Containers/Data/Application/D6530424-1CBE-4508-8C5B-7237CFD19DBE/Documents -type f -not -name '.*' | xargs -J % mv -f % /Users/brice/Library/Developer/CoreSimulator/Devices/F8B1FE98-E43C-4CA6-A98C-9616BF51889B/data/Containers/Data/Application/74192656-4549-4040-A1EB-B7B1A31BE632/Documents 

Here it tells you for example that the simulator iPad Pro has the app from version iOS 14.0 and iOS 14.2. It also prints a find command that will move all the file from the simulator iOS 14.0 (with a *) to the simulator iOS 14.2 (with a > ). It is easy to then cut and paste that function to execute the move. I currently didn’t get the utility to execute the command as I like to double check it before executing.

Note that if you want to just find the path for a specific simulator, you can add an option -n 'iPhone 11 Pro' upgrade -p to display the path of the app container as here

brice:~% -n 'iPhone 11 Pro' upgrade -p
iPhone 11 Pro has app to upgrade
     iOS 13.3[Mar 2020: 3509]  : /Users/brice/Library/Developer/CoreSimulator/Devices/5117E302-E132-43EC-9C18-83EF28B1D029/data/Containers/Data/Application/2126D354-8AFC-4C17-90A7-DD7B6D4D69FC
     iOS 13.4[May 2020: 2]     : /Users/brice/Library/Developer/CoreSimulator/Devices/25BE4F59-CF7D-4516-A031-A0694FC11C72/data/Containers/Data/Application/19AF12E0-1302-4B83-88EA-D9387E676DC3
     iOS 13.5[Jul 2020: 5926]  : /Users/brice/Library/Developer/CoreSimulator/Devices/CC981917-2002-4715-86F5-209F4F9B6493/data/Containers/Data/Application/6C246894-32BF-4869-A0B5-490E9A64E4A9
     iOS 13.6[Aug 2020: 5]     : /Users/brice/Library/Developer/CoreSimulator/Devices/7E8C7ABF-C559-4EC3-82A1-89BD3BAF246A/data/Containers/Data/Application/69BEA9CA-B99A-4B33-A92C-887B698EA98C
     iOS 13.7[Sep 2020: 4]     : /Users/brice/Library/Developer/CoreSimulator/Devices/30728C75-BC74-4FC7-A803-B30646F5889C/data/Containers/Data/Application/183AAF2C-C54B-46B7-9C9D-3662EA20827C
    *iOS 14.0[Oct 2020: 2]     : /Users/brice/Library/Developer/CoreSimulator/Devices/C4549DAA-79A7-4107-BEBD-27EDFED6C40D/data/Containers/Data/Application/CE8656FE-46F5-46BD-AD1B-65D433ACCBAD
    >iOS 14.2[Dec 2020: 7371]  : /Users/brice/Library/Developer/CoreSimulator/Devices/10C3C9FA-C357-4251-B58D-F7149D30EB78/data/Containers/Data/Application/F24D35E3-8A76-43E9-BB6D-F4A7935D8CC2
Command to execute:

find /Users/brice/Library/Developer/CoreSimulator/Devices/C4549DAA-79A7-4107-BEBD-27EDFED6C40D/data/Containers/Data/Application/CE8656FE-46F5-46BD-AD1B-65D433ACCBAD/Documents -type f -not -name '.*' | xargs -J % mv -f % /Users/brice/Library/Developer/CoreSimulator/Devices/10C3C9FA-C357-4251-B58D-F7149D30EB78/data/Containers/Data/Application/F24D35E3-8A76-43E9-BB6D-F4A7935D8CC2/Documents
     iOS 13.3[Feb 2020: 199]   : /Users/brice/Library/Developer/CoreSimulator/Devices/5117E302-E132-43EC-9C18-83EF28B1D029/data/Containers/Data/Application/4B1CFBF8-C82B-42D6-B420-D17A1382C492
     iOS 13.4[May 2020: 198]   : /Users/brice/Library/Developer/CoreSimulator/Devices/25BE4F59-CF7D-4516-A031-A0694FC11C72/data/Containers/Data/Application/7765598A-3417-4315-B749-F8D7AAC0C220
     iOS 13.5[Jun 2020: 14]    : /Users/brice/Library/Developer/CoreSimulator/Devices/CC981917-2002-4715-86F5-209F4F9B6493/data/Containers/Data/Application/80983338-3E3B-4D9C-8072-74B4CBBC5E57
     iOS 14.0[Sep 2020: 241]   : /Users/brice/Library/Developer/CoreSimulator/Devices/C4549DAA-79A7-4107-BEBD-27EDFED6C40D/data/Containers/Data/Application/CA3D2E8B-7738-4CC2-BFE1-0E73FF1D2FB7
    *iOS 14.1[Nov 2020: 12]    : /Users/brice/Library/Developer/CoreSimulator/Devices/DCCC22C0-68B7-4D79-82DB-190156234AD1/data/Containers/Data/Application/3CD5597B-C014-4318-9D4C-B31D54840B7A
    >iOS 14.2[Dec 2020: 20]    : /Users/brice/Library/Developer/CoreSimulator/Devices/10C3C9FA-C357-4251-B58D-F7149D30EB78/data/Containers/Data/Application/BC797B48-ECEA-4572-837E-B2607313B4B5
Command to execute:

find /Users/brice/Library/Developer/CoreSimulator/Devices/DCCC22C0-68B7-4D79-82DB-190156234AD1/data/Containers/Data/Application/3CD5597B-C014-4318-9D4C-B31D54840B7A/Documents -type f -not -name '.*' | xargs -J % mv -f % /Users/brice/Library/Developer/CoreSimulator/Devices/10C3C9FA-C357-4251-B58D-F7149D30EB78/data/Containers/Data/Application/BC797B48-ECEA-4572-837E-B2607313B4B5/Documents

this is quite a specialised tool, but it’s very useful to me. I hope it will help or give ideas to other to help with their workflow with the iOS simulator

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.