In Xcode 6, apple made some interesting changes to the way iOS simulators work. They are actually really interesting. The short story is, you can create your own simulators. Pick your own OS and device hardware, and a simulator is born. All you have to do is open Xcode and go to Window -> Devices and in the bottom left corner is a button to add new simulators.
This is really cool. It allows you to delete simulators that you honestly don’t care for, and recreate them if ever you do. Or, perhaps a more valuable thing you could do, is create simulators on a per project basis. Specifically for things like continuous integration or automation. That way you can ensure that if you reset the content and settings for one app, it doesn’t do it for everything, just in case you have specific requirements for Core Data or NSUserDefaults.
However, this change has caused some confusion. People are confused about where the documents directory is (link). And there are plenty of people offering advice on how to quickly find where your documents directory is for the simulator (link).
In addition, anyone who is used to running something like this
1 |
rm -rf ~/Library/Application Support/iPhone Simulator/<sdk revision> |
is in for one hell of a night, when they try this
1 2 |
#DO NOT RUN THIS COMMAND!!! rm -rf ~/Library/Developer/CoreSimulator/Devices/* |
See, inside of any device at ~/Library/Developer/CoreSimulator/Devices/ is a file called device.plist. And If you look inside, you’ll see something like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?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>UDID</key> <string>27818821-A0BB-496E-A956-EF876FB514C2</string> <key>deviceType</key> <string>com.apple.CoreSimulator.SimDeviceType.iPhone-4s</string> <key>name</key> <string>iPhone 4s</string> <key>runtime</key> <string>com.apple.CoreSimulator.SimRuntime.iOS-8-0</string> <key>state</key> <integer>1</integer> </dict> </plist> |
And as you can clearly see, the last key in the dictionary is the state. That right there should be a dead giveaway that something, somewhere is expecting things to be left as they are. And that is the case. If you just start deleting things off of your filesystem, you’ll break the simulator(s).
However, if you break things in just the right way, you can stumble upon a magical new command line tool.
simctl
simctl is a new command line tool that you can use to, as the name suggests, control the simulators. Like many tools in Xcode you run it by evoking
1 |
xcrun simctl |
This will give you the usage, and you’ll see that you can do a whole lot with the tool. And finally there is an easy way to reset the simulator from the command line.
First, you need to find out the GUID/UUID of the device you want to reset.
1 |
xcrun simctl list |
which will output something like the following
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
== Device Types == iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s) iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5) iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s) iPad 2 (com.apple.CoreSimulator.SimDeviceType.iPad-2) iPad Retina (com.apple.CoreSimulator.SimDeviceType.iPad-Retina) iPad Air (com.apple.CoreSimulator.SimDeviceType.iPad-Air) Resizable iPhone (com.apple.CoreSimulator.SimDeviceType.Resizable-iPhone) Resizable iPad (com.apple.CoreSimulator.SimDeviceType.Resizable-iPad) == Runtimes == iOS 7.0 (7.0.3 - 11B507) (com.apple.CoreSimulator.SimRuntime.iOS-7-0) iOS 7.1 (7.1 - Unknown) (com.apple.CoreSimulator.SimRuntime.iOS-7-1) (unavailable, runtime path not found) iOS 8.0 (8.0 - 12A4345d) (com.apple.CoreSimulator.SimRuntime.iOS-8-0) == Devices == -- iOS 7.0 -- iPhone 4s (F77DC0AE-6A6D-4D99-9936-F9DB07BBAA82) (Shutdown) iPhone 5 (5B78FC0D-0034-4134-8B1F-19FD0EC9D581) (Shutdown) iPhone 5s (569E5910-E32D-40E2-811F-D2E8F04EA4EF) (Shutdown) iPad 2 (451DBBD8-A387-4E77-89BF-2B3CD45B4772) (Shutdown) iPad Retina (2C58366B-5B60-4687-8031-6C67383D793F) (Shutdown) iPad Air (50E03D3B-3456-4C49-85AD-60B3AFE4918B) (Shutdown) -- iOS 7.1 -- -- iOS 8.0 -- iPhone 4s (27818821-A0BB-496E-A956-EF876FB514C2) (Shutdown) iPhone 5 (6FBAA7E2-857C-432A-BD03-980D762DA9D2) (Shutdown) iPhone 5s (7675C82B-DE49-45EB-A28D-1175376AEEE9) (Shutdown) iPad 2 (836E7C89-B9D6-4CC5-86DE-B18BA8600E7B) (Shutdown) iPad Retina (EFDD043D-2725-47DC-A3FF-C984F839A631) (Shutdown) iPad Air (9079AD6C-E74D-4D5F-9A0F-4933498B852E) (Shutdown) Resizable iPhone (943CFEDE-A03C-4298-93E3-40D0713652CB) (Shutdown) Resizable iPad (DBA71CA5-6426-484B-8E9B-13FCB3B27DEB) (Shutdown) |
Under the devices section you’ll see the GUID/UUID of the device is enclosed in parenthesis. Copy the GUID/UUID for the device you want to reset and run xcrun simctl erase <device>. For example, the following would reset the iPhone 4s (iOS 7.0)
1 |
xcrun simctl erase F77DC0AE-6A6D-4D99-9936-F9DB07BBAA82 |
Do keep in mind that simctl will not let you reset a device that is currently running. Instead it will output an error:
1 |
Unable to erase content and settings in current state: Booted |
This command line tool should make things a lot easier for people who have been trying to make Apple Scripts to click through the UI and reset all devices one at a time. It would be fairly easy to create a script to loop through all of the devices to reset them all.
You are really cool.
Sometimes, simulator devices are invalid, then I have to reset them. And you provide a beautiful answer.
A nice way to quickly remove all unused devices is with the following command:
xcrun simctl delete unavailable