Occasionally WillowTree is tasked with tracking location using our mobile apps. This enables us to do things such as change content dynamically based on where you are or track a route of a hike or a run. This can be a challenge in testing, and while we can and do take an actual run or drive to check that we’re updating the location accurately, this can take a lot of time and is limited to only our local area. To save time or check how the product works in a remote location, we can simulate location. We do this using Xcode. While there are other methods, Xcode does not require wiping the device and can be used with the latest version of iOS. The following steps assume you have an existing project running from Xcode on your mac. While you can set location easily using the Simulator, Xcode provides much more powerful tools for setting custom locations and even simulating movement. Here we’ll go over each option step by step.
Setting location in the simulator:
- Once you have your app running in the simulator, navigate to Debug→Location in the menu.
- Apple gives you 4 default locations/routes all in and around Cupertino in addition to Custom Location… where you can manually input the latitude and longitude. There are many places to get latitude and longitude, one of the most recognizable would be google maps.
- To get the latitude and longitude from google maps simply click on the map at the location you want the info for
- You will see something like this at the bottom of the screen:
- Here the latitude is 38.029401 and the longitude is -78.478768. These can be copied into the dialog above.
Setting the location in the scheme before building:
- In Xcode with the project open and a device connected, navigate to Product→Scheme→Edit Scheme
- With Run selected on the left select the Options tab on the right
- Check Allow Location Simulation (note: this will only show if a device is connected). You can now simulate your location
To set a default location to be used when the app is run from Xcode
- Click the dropdown next to Default Location and select any location you want
- The next time the app is run it will use whatever you’ve selected
Setting a location after a build is running (Allow Location Simulation must be enabled in the Scheme):
- Navigate to Debug→Simulate Location and select any location in the list. The device should immediately start using that location
The device or simulator should now show as at the location you have selected. Once you’re running the app with a new location you may need to open the maps app to force the system to update the location. You may have noticed when setting the location in the scheme or after the app is running, the option to Add GPX File to Workspace… The built in locations are useful but sometimes you want to check a specific location on a device. Say you want to show the user information about the local football team that is not in any of the default cities. To do that you’ll need a custom GPX file. Getting a GPX file A GPX file uses latitude and longitude to specify location, first you’ll need to find this data. See above for a quick way to obtain this from google maps. Next you’ll need to create the GPX file You can use Xcode to create the GPX file In Xcode navigate to File→New→File… This will give you the option to select a template The ‘GPX’ template should be under macOS, you may filter by ‘gpx’ and you should see the option, select and click Next: The next dialog allows you to specify a location and name etc. Once it’s created it is filled with location data for Cupertino and some helpful hints. You can enter the latitude and longitude you want in place of the default. You can also manually create a GPX file, a GPX file is just a text file with the .gpx extension. The below example will put your device in Los Angeles.
<gpx> <wpt lat="34.0625905" lon="-118.36230069999999"></wpt> </gpx>
Now you have a GPX file! Select it in your scheme before running or in the menu while running the app on your device. The final option is to simulate movement. This is a powerful tool that can be used to track a route say for a hike or a run, or the speed of the user in general. To do this you will need a GPX file with multiple points. If you created a GPX file using Xcode, you will see the following: Optionally provide a time element for each waypoint. Xcode will interpolate movement at a rate of speed based on the time elapsed between each waypoint. If you do not provide a time element, then Xcode will use a fixed rate of speed. Waypoints must be sorted by time in ascending order. Following the above I’ve created a GPX file for a very short walk in Charlottesville.
<gpx> <wpt lon="-78.4814684" lat="38.0283608"> <name>TP001</name> <ele>139.36167907715</ele> <time>2017-05-18T12:20:25Z</time> </wpt> <wpt lon="-78.48174" lat="38.02844"> <name>TP002</name> <ele>139.58670043945</ele> <time>2017-05-18T12:20:37Z</time> </wpt> <wpt lon="-78.4817437" lat="38.0284428"> <name>TP003</name> <ele>139.79161071777</ele> <time>2017-05-18T12:20:39Z</time> </wpt> <wpt lon="-78.48159" lat="38.02877"> <name>TP004</name> <ele>139.78443908691</ele> <time>2017-05-18T12:21:14Z</time> </wpt> <wpt lon="-78.48156" lat="38.02885"> <name>TP005</name> <ele>138.47015380859</ele> <time>2017-05-18T12:21:22Z</time> </wpt> <wpt lon="-78.48149" lat="38.02899"> <name>TP006</name> <ele>137.04736328125</ele> <time>2017-05-18T12:21:37Z</time> </wpt> <wpt lon="-78.48147" lat="38.02902"> <name>TP007</name> <ele>136.67156982422</ele> <time>2017-05-18T12:21:40Z</time> </wpt> <wpt lon="-78.48144" lat="38.02913"> <name>TP008</name> <ele>137.19146728516</ele> <time>2017-05-18T12:21:51Z</time> </wpt> <wpt lon="-78.4811" lat="38.02981"> <name>TP009</name> <ele>139.01919555664</ele> <time>2017-05-18T12:23:04Z</time> </wpt> <wpt lon="-78.48096" lat="38.03007"> <name>TP010</name> <ele>140.29809570312</ele> <time>2017-05-18T12:23:22Z</time> </wpt> <wpt lon="-78.48074" lat="38.03057"> <name>TP011</name> <ele>140.81834411621</ele> <time>2017-05-18T12:23:55Z</time> </wpt> <wpt lon="-78.48058" lat="38.03094"> <name>TP012</name> <ele>145.85939025879</ele> <time>2017-05-18T12:24:19Z</time> </wpt> <wpt lon="-78.48054" lat="38.03103"> <name>TP013</name> <ele>144.88935852051</ele> <time>2017-05-18T12:24:25Z</time> </wpt> </gpx>
You can see there are additional tags (
<ele>) not mentioned by the notes Xcode generates. These tags are ignored by Xcode currently (sorry Pokémon Go spoofers!).
There are many tools to create large GPX files easily. My favorite is mapstogpx, which will generate GPX files from directions from google maps. If you’re using other tools, you may run into a popular format used by bikers that uses the
<trk> tag. Often these can easily be converted to work with Xcode via find and replace and/or regex.
After disconnecting your device or simulator it may still use the simulated location. If this is an issue, you can restart the device or use Reset Content and Settings in device settings.